Decompiled source of FishsGrandAdventure v1.2.6

FishsGrandAdventure.dll

Decompiled a year ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using FishsGrandAdventure.Audio;
using FishsGrandAdventure.Behaviors;
using FishsGrandAdventure.Game;
using FishsGrandAdventure.Game.Events;
using FishsGrandAdventure.Network;
using FishsGrandAdventure.Utils;
using FishsGrandAdventure.Utils.Converters;
using GameNetcodeStuff;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("Fish Clan")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Private mod for the Fish Clan")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FishsGrandAdventure")]
[assembly: AssemblyTitle("FishsGrandAdventure")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FishsGrandAdventure
{
	public static class ModInfo
	{
		public const string Guid = "FishsGrandAdventure";

		public const string Name = "Fish's Grand Adventure";

		public const string Version = "1.2.6";

		public static string[] Dependencies => new string[0];
	}
	[BepInPlugin("FishsGrandAdventure", "Fish's Grand Adventure", "1.2.6")]
	public class Plugin : BaseUnityPlugin
	{
		public static string FileLocation;

		public static ManualLogSource Log;

		public static MethodInfo Chat;

		private static bool loaded;

		private readonly Harmony harmony = new Harmony("NavidK0.FishsGrandAdventure");

		private void Awake()
		{
			FileLocation = ((BaseUnityPlugin)this).Info.Location;
			Log = ((BaseUnityPlugin)this).Logger;
			Chat = AccessTools.Method(typeof(HUDManager), "AddChatMessage", (Type[])null, (Type[])null);
			Log.LogInfo((object)"Loading Fish's Grand Adventure...");
			harmony.PatchAll(typeof(GameEventManager));
			harmony.PatchAll(typeof(NetworkTransportPatch));
			harmony.PatchAll(typeof(PatchClownWorld));
			harmony.PatchAll(typeof(PatchClownExpo));
			harmony.PatchAll(typeof(PatchSpeedRun));
			harmony.PatchAll(typeof(PatchSeaWorld));
			harmony.PatchAll(typeof(PatchRackAndRoll));
			harmony.PatchAll(typeof(PatchEscapeFactoryEvent));
			harmony.PatchAll(typeof(CommandListener));
			harmony.PatchAll(typeof(CustomMoonManager));
			harmony.PatchAll(typeof(PlayerControllerBPatcher));
			NetworkTransport.GetString = (Action<string, string>)Delegate.Combine(NetworkTransport.GetString, new Action<string, string>(NetworkUtils.OnMessageReceived));
		}

		public void OnDestroy()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			if (!loaded)
			{
				GameObject val = new GameObject("FishsGrandAdventure.GameEventManager");
				val.AddComponent<GameEventManager>();
				Object.DontDestroyOnLoad((Object)(object)val);
				Log.LogInfo((object)"Added GameEventManager");
				GameObject val2 = new GameObject("FishsGrandAdventure.AudioManager");
				val.AddComponent<AudioManager>();
				Object.DontDestroyOnLoad((Object)(object)val2);
				Log.LogInfo((object)"Added AudioManager");
				loaded = true;
				Log.LogInfo((object)"Loaded Fish's Grand Adventure v1.2.6");
			}
		}
	}
}
namespace FishsGrandAdventure.Utils
{
	[PublicAPI]
	public static class ColorUtils
	{
		public const double Tolerance = 9.999999974752427E-07;

		public static readonly Color32 Black = new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue);

		public static readonly Color32 Transparent = new Color32((byte)0, (byte)0, (byte)0, (byte)0);

		public static readonly Color32 Marker = new Color32(byte.MaxValue, (byte)0, byte.MaxValue, byte.MaxValue);

		public static readonly Color32 Teal = new Color32((byte)0, byte.MaxValue, byte.MaxValue, byte.MaxValue);

		public static readonly Color32 TealA1 = new Color32((byte)0, byte.MaxValue, byte.MaxValue, (byte)1);

		public static readonly Color32 Purple = Color32.op_Implicit(new Color(0.69f, 0f, 1f));

		public static readonly Color32 Orange = Color32.op_Implicit(new Color(1f, 0.65f, 0f));

		public static readonly Color32 LightBlue = Color32.op_Implicit(new Color(0f, 0.87f, 1f));

		public static readonly Color32 Yellow = Color32.op_Implicit(new Color(1f, 1f, 0f));

		public static readonly Color32 Bronze = new Color32((byte)205, (byte)127, (byte)50, byte.MaxValue);

		public static readonly Color32 Silver = new Color32((byte)192, (byte)192, (byte)192, byte.MaxValue);

		public static readonly Color32 Gold = new Color32(byte.MaxValue, (byte)247, (byte)0, byte.MaxValue);

		public static readonly Color32 Platinum = new Color32((byte)229, (byte)228, (byte)226, byte.MaxValue);

		public static Color WithAlpha(this Color color, float alpha)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			color.a = alpha;
			return color;
		}

		public static Color WithAlpha(this Color color, byte alpha)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			color.a = alpha.ToFloat();
			return color;
		}

		public static Color32 WithAlpha(this Color32 color, byte alpha)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			color.a = alpha;
			return color;
		}

		public static Color32 WithAlpha(this Color32 color, float alpha)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			color.a = alpha.ToByte();
			return color;
		}

		public static Color KeepAlpha(this Color color, Color newColor)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			newColor.a = color.a;
			return newColor;
		}

		public static Color32 KeepAlpha(this Color32 color, Color32 newColor)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			newColor.a = color.a;
			return newColor;
		}

		public static Color Clone(this Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			return new Color(color.r, color.g, color.b, color.a);
		}

		public static bool SameAs(ref Color32 a, ref Color32 b)
		{
			return a.a == b.a && a.b == b.b && a.g == b.g && a.r == b.r;
		}

		public static bool SameAs(ref Color a, ref Color b)
		{
			return (double)Mathf.Abs(a.a - b.a) < 9.999999974752427E-07 && (double)Mathf.Abs(a.b - b.b) < 9.999999974752427E-07 && (double)Mathf.Abs(a.g - b.g) < 9.999999974752427E-07 && (double)Mathf.Abs(a.r - b.r) < 9.999999974752427E-07;
		}

		public static Color InvertColor(this Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			return new Color(1f - color.r, 1f - color.g, 1f - color.b);
		}

		public static Color RandomNonDarkColor()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			return Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);
		}

		public static Color RandomColor()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			return Random.ColorHSV(0f, 1f, 0f, 1f, 0.5f, 1f);
		}

		public static float LinearToGamma(float val)
		{
			return Mathf.Pow(val, 0.4545454f);
		}

		public static float GammaToLinear(float val)
		{
			return Mathf.Pow(val, 2.2f);
		}

		public static string ToHex(this Color c)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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)
			return $"{c.r.ToByte():X2}{c.g.ToByte():X2}{c.b.ToByte():X2}{c.a.ToByte():X2}";
		}

		public static string ToHex(this Color32 c)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			return $"{c.r:X2}{c.g:X2}{c.b:X2}{c.a:X2}";
		}
	}
	public static class CopyUtils
	{
		public static void CopyLevelProperties(ref SelectableLevel level, SelectableLevel original)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			level.planetPrefab = original.planetPrefab;
			level.sceneName = original.sceneName;
			level.spawnEnemiesAndScrap = original.spawnEnemiesAndScrap;
			level.PlanetName = original.PlanetName;
			level.LevelDescription = original.LevelDescription;
			level.videoReel = original.videoReel;
			level.riskLevel = original.riskLevel;
			level.timeToArrive = original.timeToArrive;
			level.OffsetFromGlobalTime = original.OffsetFromGlobalTime;
			level.DaySpeedMultiplier = original.DaySpeedMultiplier;
			level.planetHasTime = original.planetHasTime;
			level.randomWeathers = original.randomWeathers;
			level.overrideWeather = original.overrideWeather;
			level.overrideWeatherType = original.overrideWeatherType;
			level.currentWeather = original.currentWeather;
			level.factorySizeMultiplier = original.factorySizeMultiplier;
			level.dungeonFlowTypes = original.dungeonFlowTypes.DeepCopy();
			level.spawnableMapObjects = original.spawnableMapObjects.DeepCopy();
			level.spawnableOutsideObjects = original.spawnableOutsideObjects.DeepCopy();
			level.spawnableScrap = original.spawnableScrap.DeepCopy();
			level.minTotalScrapValue = original.minTotalScrapValue;
			level.maxTotalScrapValue = original.maxTotalScrapValue;
			level.levelAmbienceClips = original.levelAmbienceClips;
			level.Enemies = original.Enemies.DeepCopy();
			level.OutsideEnemies = original.OutsideEnemies.DeepCopy();
			level.DaytimeEnemies = original.DaytimeEnemies.DeepCopy();
			level.outsideEnemySpawnChanceThroughDay = original.outsideEnemySpawnChanceThroughDay;
			level.spawnProbabilityRange = original.spawnProbabilityRange;
			level.daytimeEnemiesProbabilityRange = original.daytimeEnemiesProbabilityRange;
			level.levelIncludesSnowFootprints = original.levelIncludesSnowFootprints;
			level.levelIconString = original.levelIconString;
		}

		public static EnemyType DeepCopy(this EnemyType enemy)
		{
			EnemyType val = ScriptableObject.CreateInstance<EnemyType>();
			val.enemyName = enemy.enemyName;
			val.probabilityCurve = enemy.probabilityCurve;
			val.numberSpawnedFalloff = enemy.numberSpawnedFalloff;
			val.useNumberSpawnedFalloff = enemy.useNumberSpawnedFalloff;
			val.enemyPrefab = enemy.enemyPrefab;
			val.PowerLevel = enemy.PowerLevel;
			val.MaxCount = enemy.MaxCount;
			val.numberSpawned = enemy.numberSpawned;
			val.isOutsideEnemy = enemy.isOutsideEnemy;
			val.isDaytimeEnemy = enemy.isDaytimeEnemy;
			val.normalizedTimeInDayToLeave = enemy.normalizedTimeInDayToLeave;
			val.stunTimeMultiplier = enemy.stunTimeMultiplier;
			val.doorSpeedMultiplier = enemy.doorSpeedMultiplier;
			val.canBeStunned = enemy.canBeStunned;
			val.canDie = enemy.canDie;
			val.destroyOnDeath = enemy.destroyOnDeath;
			val.canSeeThroughFog = enemy.canSeeThroughFog;
			val.timeToPlayAudio = enemy.timeToPlayAudio;
			val.loudnessMultiplier = enemy.loudnessMultiplier;
			val.overrideVentSFX = enemy.overrideVentSFX;
			val.hitBodySFX = enemy.hitBodySFX;
			val.hitEnemyVoiceSFX = enemy.hitEnemyVoiceSFX;
			val.deathSFX = enemy.deathSFX;
			val.stunSFX = enemy.stunSFX;
			val.miscAnimations = (MiscAnimation[])enemy.miscAnimations.Clone();
			val.audioClips = (AudioClip[])enemy.audioClips.Clone();
			return val;
		}

		public static Item DeepCopy(this Item item)
		{
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			Item val = ScriptableObject.CreateInstance<Item>();
			val.itemName = item.itemName;
			val.spawnPositionTypes = new List<ItemGroup>(item.spawnPositionTypes);
			val.twoHanded = item.twoHanded;
			val.twoHandedAnimation = item.twoHandedAnimation;
			val.canBeGrabbedBeforeGameStart = item.canBeGrabbedBeforeGameStart;
			val.weight = item.weight;
			val.itemIsTrigger = item.itemIsTrigger;
			val.holdButtonUse = item.holdButtonUse;
			val.itemSpawnsOnGround = item.itemSpawnsOnGround;
			val.isConductiveMetal = item.isConductiveMetal;
			val.isScrap = item.isScrap;
			val.creditsWorth = item.creditsWorth;
			val.highestSalePercentage = item.highestSalePercentage;
			val.maxValue = item.maxValue;
			val.minValue = item.minValue;
			val.spawnPrefab = item.spawnPrefab;
			val.requiresBattery = item.requiresBattery;
			val.batteryUsage = item.batteryUsage;
			val.automaticallySetUsingPower = item.automaticallySetUsingPower;
			val.itemIcon = item.itemIcon;
			val.grabAnim = item.grabAnim;
			val.useAnim = item.useAnim;
			val.pocketAnim = item.pocketAnim;
			val.throwAnim = item.throwAnim;
			val.grabAnimationTime = item.grabAnimationTime;
			val.grabSFX = item.grabSFX;
			val.dropSFX = item.dropSFX;
			val.pocketSFX = item.pocketSFX;
			val.throwSFX = item.throwSFX;
			val.syncGrabFunction = item.syncGrabFunction;
			val.syncDiscardFunction = item.syncDiscardFunction;
			val.syncInteractLRFunction = item.syncInteractLRFunction;
			val.saveItemVariable = item.saveItemVariable;
			val.isDefensiveWeapon = item.isDefensiveWeapon;
			val.toolTips = item.toolTips;
			val.verticalOffset = item.verticalOffset;
			val.floorYOffset = item.floorYOffset;
			val.allowDroppingAheadOfPlayer = item.allowDroppingAheadOfPlayer;
			val.restingRotation = item.restingRotation;
			val.rotationOffset = item.rotationOffset;
			val.positionOffset = item.positionOffset;
			val.meshOffset = item.meshOffset;
			val.meshVariants = (Mesh[])item.meshVariants.Clone();
			val.materialVariants = (Material[])item.materialVariants.Clone();
			val.usableInSpecialAnimations = item.usableInSpecialAnimations;
			val.canBeInspected = item.canBeInspected;
			return val;
		}

		public static SelectableLevel DeepCopy(this SelectableLevel level)
		{
			SelectableLevel level2 = ScriptableObject.CreateInstance<SelectableLevel>();
			CopyLevelProperties(ref level2, level);
			return level2;
		}

		public static IntWithRarity[] DeepCopy(this IntWithRarity[] array)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			IntWithRarity[] array2 = (IntWithRarity[])(object)new IntWithRarity[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array2[i] = new IntWithRarity
				{
					id = array[i].id,
					rarity = array[i].rarity
				};
			}
			return array2;
		}

		public static RandomWeatherWithVariables[] DeepCopy(this RandomWeatherWithVariables[] array)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			RandomWeatherWithVariables[] array2 = (RandomWeatherWithVariables[])(object)new RandomWeatherWithVariables[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array2[i] = new RandomWeatherWithVariables
				{
					weatherType = array[i].weatherType,
					weatherVariable = array[i].weatherVariable,
					weatherVariable2 = array[i].weatherVariable2
				};
			}
			return array2;
		}

		public static SpawnableMapObject[] DeepCopy(this SpawnableMapObject[] array)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			SpawnableMapObject[] array2 = (SpawnableMapObject[])(object)new SpawnableMapObject[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array2[i] = new SpawnableMapObject
				{
					prefabToSpawn = array[i].prefabToSpawn,
					numberToSpawn = array[i].numberToSpawn,
					spawnFacingAwayFromWall = array[i].spawnFacingAwayFromWall
				};
			}
			return array2;
		}

		public static SpawnableOutsideObjectWithRarity[] DeepCopy(this SpawnableOutsideObjectWithRarity[] array)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			SpawnableOutsideObjectWithRarity[] array2 = (SpawnableOutsideObjectWithRarity[])(object)new SpawnableOutsideObjectWithRarity[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array2[i] = new SpawnableOutsideObjectWithRarity
				{
					spawnableObject = array[i].spawnableObject,
					randomAmount = array[i].randomAmount
				};
			}
			return array2;
		}

		public static List<SpawnableEnemyWithRarity> DeepCopy(this List<SpawnableEnemyWithRarity> list)
		{
			//IL_001b: 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)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			List<SpawnableEnemyWithRarity> list2 = new List<SpawnableEnemyWithRarity>();
			foreach (SpawnableEnemyWithRarity item in list)
			{
				list2.Add(new SpawnableEnemyWithRarity
				{
					enemyType = item.enemyType.DeepCopy(),
					rarity = item.rarity
				});
			}
			return list2;
		}

		public static List<SpawnableItemWithRarity> DeepCopy(this List<SpawnableItemWithRarity> list)
		{
			//IL_001b: 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)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			List<SpawnableItemWithRarity> list2 = new List<SpawnableItemWithRarity>();
			foreach (SpawnableItemWithRarity item in list)
			{
				list2.Add(new SpawnableItemWithRarity
				{
					spawnableItem = item.spawnableItem.DeepCopy(),
					rarity = item.rarity
				});
			}
			return list2;
		}
	}
	public static class DelegateUtils
	{
		private static readonly PropertyInfo PluginGetLogger = AccessTools.Property(typeof(BaseUnityPlugin), "Logger");

		public static void InvokeActionSafe(this Action action)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			if (action == null)
			{
				return;
			}
			Delegate[] invocationList = action.GetInvocationList();
			foreach (Delegate @delegate in invocationList)
			{
				try
				{
					Action action2 = (Action)@delegate;
					action2();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)"Exception while invoking hook callback!");
					string asmName = @delegate.GetMethodInfo().DeclaringType.Assembly.FullName;
					PluginInfo val = ((IEnumerable<PluginInfo>)Chainloader.PluginInfos.Values).FirstOrDefault((Func<PluginInfo, bool>)((PluginInfo pi) => ((object)pi.Instance).GetType().Assembly.FullName == asmName));
					if (val == null)
					{
						Plugin.Log.LogError((object)ex.ToString());
						break;
					}
					ManualLogSource val2 = (ManualLogSource)PluginGetLogger.GetValue(val.Instance);
					val2.LogError((object)ex.ToString());
				}
			}
		}

		public static void InvokeActionSafe<T>(this Action<T> action, T param)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			if (action == null)
			{
				return;
			}
			Delegate[] invocationList = action.GetInvocationList();
			foreach (Delegate @delegate in invocationList)
			{
				try
				{
					Action<T> action2 = (Action<T>)@delegate;
					action2(param);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)"Exception while invoking hook callback!");
					string asmName = @delegate.GetMethodInfo().DeclaringType.Assembly.FullName;
					PluginInfo val = ((IEnumerable<PluginInfo>)Chainloader.PluginInfos.Values).FirstOrDefault((Func<PluginInfo, bool>)((PluginInfo pi) => ((object)pi.Instance).GetType().Assembly.FullName == asmName));
					if (val == null)
					{
						Plugin.Log.LogError((object)ex.ToString());
						break;
					}
					ManualLogSource val2 = (ManualLogSource)PluginGetLogger.GetValue(val.Instance);
					val2.LogError((object)ex.ToString());
				}
			}
		}

		public static void InvokeActionSafe<T1, T2>(this Action<T1, T2> action, T1 param1, T2 param2)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			if (action == null)
			{
				return;
			}
			Delegate[] invocationList = action.GetInvocationList();
			foreach (Delegate @delegate in invocationList)
			{
				try
				{
					Action<T1, T2> action2 = (Action<T1, T2>)@delegate;
					action2(param1, param2);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)"Exception while invoking hook callback!");
					string asmName = @delegate.GetMethodInfo().DeclaringType.Assembly.FullName;
					PluginInfo val = ((IEnumerable<PluginInfo>)Chainloader.PluginInfos.Values).FirstOrDefault((Func<PluginInfo, bool>)((PluginInfo pi) => ((object)pi.Instance).GetType().Assembly.FullName == asmName));
					if (val == null)
					{
						Plugin.Log.LogError((object)ex.ToString());
						break;
					}
					ManualLogSource val2 = (ManualLogSource)PluginGetLogger.GetValue(val.Instance);
					val2.LogError((object)ex.ToString());
				}
			}
		}

		internal static void InvokeParameterlessDelegate<T>(this T paramlessDelegate) where T : Delegate
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			if ((Delegate?)paramlessDelegate == (Delegate?)null)
			{
				return;
			}
			Delegate[] invocationList = paramlessDelegate.GetInvocationList();
			foreach (Delegate @delegate in invocationList)
			{
				try
				{
					T val = (T)@delegate;
					val.DynamicInvoke();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)"Exception while invoking hook callback!");
					string asmName = @delegate.GetMethodInfo().DeclaringType.Assembly.FullName;
					PluginInfo val2 = ((IEnumerable<PluginInfo>)Chainloader.PluginInfos.Values).FirstOrDefault((Func<PluginInfo, bool>)((PluginInfo pi) => ((object)pi.Instance).GetType().Assembly.FullName == asmName));
					if (val2 == null)
					{
						Plugin.Log.LogError((object)ex.ToString());
						break;
					}
					ManualLogSource val3 = (ManualLogSource)PluginGetLogger.GetValue(val2.Instance);
					val3.LogError((object)ex.ToString());
				}
			}
		}
	}
	[PublicAPI]
	public static class EnumerableUtils
	{
		private static readonly Random Rng = new Random();

		public static List<T> Shuffle<T>(this T[] array)
		{
			List<T> list = array.ToList();
			list.Shuffle();
			return list;
		}

		public static List<T> Shuffle<T>(this IEnumerable<T> list)
		{
			List<T> list2 = list.ToList();
			list2.Shuffle();
			return list2;
		}

		public static List<T> Shuffle<T>(this IEnumerable<T> list, Random random)
		{
			List<T> list2 = list.ToList();
			list2.Shuffle(random);
			return list2;
		}

		public static void Shuffle<T>(this IList<T> list)
		{
			for (int num = list.Count - 1; num > 1; num--)
			{
				int index = Rng.Next(num + 1);
				T value = list[num];
				T value2 = list[index];
				list[num] = value2;
				list[index] = value;
			}
		}

		public static void Shuffle<T>(this IList<T> list, Random random)
		{
			for (int num = list.Count - 1; num > 1; num--)
			{
				int index = random.Next(num + 1);
				T value = list[num];
				T value2 = list[index];
				list[num] = value2;
				list[index] = value;
			}
		}

		public static T GetRandomElement<T>(this IEnumerable<T> enumerable, bool ignoreNull = false)
		{
			return enumerable.ToList().GetRandomElement();
		}

		public static T GetRandomElement<T>(this List<T> list, bool noRepeats = false, bool ignoreNull = false)
		{
			if (ignoreNull)
			{
				List<T> list2 = new List<T>(list);
				list2.RemoveAll((T x) => x == null);
				return list2[Rng.Next(list2.Count)];
			}
			try
			{
				return list[Rng.Next(list.Count)];
			}
			catch (Exception)
			{
				return default(T);
			}
		}

		public static T GetRandomElement<T>(this List<T> list, Random random)
		{
			try
			{
				return list[random.Next(list.Count)];
			}
			catch (Exception)
			{
				return default(T);
			}
		}

		public static T GetRandomElementByWeight<T>(this List<T> sequence, Func<T, float> weightSelector)
		{
			List<T> source = sequence.ToList();
			float num = source.Sum(weightSelector);
			float num2 = (float)Rng.NextDouble() * num;
			float num3 = 0f;
			foreach (var item in source.Select((T weightedItem) => new
			{
				Value = weightedItem,
				Weight = weightSelector(weightedItem)
			}))
			{
				num3 += item.Weight;
				if (num3 >= num2)
				{
					return item.Value;
				}
			}
			return default(T);
		}

		public static T[][] CreateJaggedArray<T>(this IList<T[]> arrays)
		{
			int num = arrays[0].Length;
			T[][] array = new T[arrays.Count][];
			for (int i = 0; i < num; i++)
			{
				array[i] = new T[arrays[i].Length];
			}
			for (int j = 0; j < arrays.Count; j++)
			{
				T[] array2 = arrays[j];
				if (array2.Length != num)
				{
					throw new ArgumentException("All arrays must be the same length");
				}
				for (int k = 0; k < num; k++)
				{
					array[j][k] = array2[k];
				}
			}
			return array;
		}

		public static string ConvertToString<T>(this IList<T> list)
		{
			return "[" + string.Join(",", list) + "]";
		}

		public static bool IsEmpty<T>(this IList<T> list)
		{
			return list.Count == 0;
		}

		public static bool IsNullOrEmpty<T>(this IList<T> list)
		{
			if (list != null)
			{
				return list.Count == 0;
			}
			return true;
		}

		public static IEnumerable<T> Examine<T>(this IEnumerable<T> source, Action<T> action)
		{
			foreach (T obj in source)
			{
				action(obj);
				yield return obj;
			}
		}

		public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T> action)
		{
			List<T> list = source.ToList();
			foreach (T item in list)
			{
				action(item);
			}
			return list;
		}

		public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T, int> action)
		{
			int num = 0;
			T[] array = (source as T[]) ?? source.ToArray();
			T[] array2 = array;
			foreach (T arg in array2)
			{
				action(arg, num++);
			}
			return array;
		}

		public static IEnumerable<T> Convert<T>(this IEnumerable source, Func<object, T> converter)
		{
			foreach (object obj in source)
			{
				yield return converter(obj);
			}
		}

		public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)
		{
			return new HashSet<T>(source);
		}

		public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer)
		{
			return new HashSet<T>(source, comparer);
		}

		public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, Func<T> prepend)
		{
			yield return prepend();
			foreach (T item in source)
			{
				yield return item;
			}
		}

		public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, T prepend)
		{
			yield return prepend;
			foreach (T item in source)
			{
				yield return item;
			}
		}

		public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, IEnumerable<T> prepend)
		{
			foreach (T item in prepend)
			{
				yield return item;
			}
			foreach (T item2 in source)
			{
				yield return item2;
			}
		}

		public static IEnumerable<T> PrependIf<T>(this IEnumerable<T> source, bool condition, Func<T> prepend)
		{
			if (condition)
			{
				yield return prepend();
			}
			foreach (T item in source)
			{
				yield return item;
			}
		}

		public static IEnumerable<T> PrependIf<T>(this IEnumerable<T> source, bool condition, T prepend)
		{
			if (condition)
			{
				yield return prepend;
			}
			foreach (T item in source)
			{
				yield return item;
			}
		}

		public static IEnumerable<T> PrependIf<T>(this IEnumerable<T> source, bool condition, IEnumerable<T> prepend)
		{
			if (condition)
			{
				foreach (T item in prepend)
				{
					yield return item;
				}
			}
			foreach (T item2 in source)
			{
				yield return item2;
			}
		}

		public static IEnumerable<T> PrependIf<T>(this IEnumerable<T> source, Func<bool> condition, Func<T> prepend)
		{
			if (condition())
			{
				yield return prepend();
			}
			foreach (T item in source)
			{
				yield return item;
			}
		}

		public static IEnumerable<T> PrependIf<T>(this IEnumerable<T> source, Func<bool> condition, T prepend)
		{
			if (condition())
			{
				yield return prepend;
			}
			foreach (T item in source)
			{
				yield return item;
			}
		}

		public static IEnumerable<T> PrependIf<T>(this IEnumerable<T> source, Func<bool> condition, IEnumerable<T> prepend)
		{
			if (condition())
			{
				foreach (T item in prepend)
				{
					yield return item;
				}
			}
			foreach (T item2 in source)
			{
				yield return item2;
			}
		}

		public static IEnumerable<T> PrependIf<T>(this IEnumerable<T> source, Func<IEnumerable<T>, bool> condition, Func<T> prepend)
		{
			List<T> enumerable = source.ToList();
			if (condition(enumerable))
			{
				yield return prepend();
			}
			foreach (T item in enumerable)
			{
				yield return item;
			}
		}

		public static IEnumerable<T> PrependIf<T>(this IEnumerable<T> source, Func<IEnumerable<T>, bool> condition, T prepend)
		{
			List<T> enumerable = source.ToList();
			if (condition(enumerable))
			{
				yield return prepend;
			}
			foreach (T item in enumerable)
			{
				yield return item;
			}
		}

		public static IEnumerable<T> PrependIf<T>(this IEnumerable<T> source, Func<IEnumerable<T>, bool> condition, IEnumerable<T> prepend)
		{
			List<T> enumerable = source.ToList();
			if (condition(enumerable))
			{
				foreach (T item in prepend)
				{
					yield return item;
				}
			}
			foreach (T item2 in enumerable)
			{
				yield return item2;
			}
		}

		public static IEnumerable<T> Append<T>(this IEnumerable<T> source, Func<T> append)
		{
			foreach (T item in source)
			{
				yield return item;
			}
			yield return append();
		}

		public static IEnumerable<T> Append<T>(this IEnumerable<T> source, T append)
		{
			foreach (T item in source)
			{
				yield return item;
			}
			yield return append;
		}

		public static IEnumerable<T> Append<T>(this IEnumerable<T> source, IEnumerable<T> append)
		{
			foreach (T item in source)
			{
				yield return item;
			}
			foreach (T item2 in append)
			{
				yield return item2;
			}
		}

		public static IEnumerable<T> AppendIf<T>(this IEnumerable<T> source, bool condition, Func<T> append)
		{
			foreach (T item in source)
			{
				yield return item;
			}
			if (condition)
			{
				yield return append();
			}
		}

		public static IEnumerable<T> AppendIf<T>(this IEnumerable<T> source, bool condition, T append)
		{
			foreach (T item in source)
			{
				yield return item;
			}
			if (condition)
			{
				yield return append;
			}
		}

		public static IEnumerable<T> AppendIf<T>(this IEnumerable<T> source, bool condition, IEnumerable<T> append)
		{
			foreach (T item in source)
			{
				yield return item;
			}
			if (!condition)
			{
				yield break;
			}
			foreach (T item2 in append)
			{
				yield return item2;
			}
		}

		public static IEnumerable<T> AppendIf<T>(this IEnumerable<T> source, Func<bool> condition, Func<T> append)
		{
			foreach (T item in source)
			{
				yield return item;
			}
			if (condition())
			{
				yield return append();
			}
		}

		public static IEnumerable<T> AppendIf<T>(this IEnumerable<T> source, Func<bool> condition, T append)
		{
			foreach (T item in source)
			{
				yield return item;
			}
			if (condition())
			{
				yield return append;
			}
		}

		public static IEnumerable<T> AppendIf<T>(this IEnumerable<T> source, Func<bool> condition, IEnumerable<T> append)
		{
			foreach (T item in source)
			{
				yield return item;
			}
			if (!condition())
			{
				yield break;
			}
			foreach (T item2 in append)
			{
				yield return item2;
			}
		}

		public static IEnumerable<T> FilterCast<T>(this IEnumerable source)
		{
			T variable = default(T);
			foreach (object obj in source)
			{
				int num;
				if (obj is T)
				{
					variable = (T)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				if (num != 0)
				{
					yield return variable;
				}
				variable = default(T);
			}
		}

		public static void AddRange<T>(this HashSet<T> hashSet, IEnumerable<T> range)
		{
			foreach (T item in range)
			{
				hashSet.Add(item);
			}
		}

		public static void Populate<T>(this IList<T> list, T item)
		{
			int count = list.Count;
			for (int i = 0; i < count; i++)
			{
				list[i] = item;
			}
		}

		public static void AddRange<T>(this IList<T> list, IEnumerable<T> collection)
		{
			if (list is List<T> list2)
			{
				list2.AddRange(collection);
				return;
			}
			foreach (T item in collection)
			{
				list.Add(item);
			}
		}

		public static void Sort<T>(this IList<T> list, Comparison<T> comparison)
		{
			if (list is List<T> list2)
			{
				list2.Sort(comparison);
				return;
			}
			List<T> list3 = new List<T>(list);
			list3.Sort(comparison);
			for (int i = 0; i < list.Count; i++)
			{
				list[i] = list3[i];
			}
		}

		public static void Sort<T>(this IList<T> list)
		{
			if (list is List<T> list2)
			{
				list2.Sort();
				return;
			}
			List<T> list3 = new List<T>(list);
			list3.Sort();
			for (int i = 0; i < list.Count; i++)
			{
				list[i] = list3[i];
			}
		}

		public static int FindIndex<T>(this IEnumerable<T> items, Func<T, bool> predicate)
		{
			if (items == null)
			{
				throw new ArgumentNullException("items");
			}
			if (predicate == null)
			{
				throw new ArgumentNullException("predicate");
			}
			int num = 0;
			foreach (T item in items)
			{
				if (predicate(item))
				{
					return num;
				}
				num++;
			}
			return -1;
		}

		public static int IndexOf<T>(this IEnumerable<T> items, T item)
		{
			return items.FindIndex((T i) => EqualityComparer<T>.Default.Equals(item, i));
		}

		public static T Find<T>(this T[] items, Predicate<T> predicate)
		{
			return Array.Find(items, predicate);
		}

		public static T[] FindAll<T>(this T[] items, Predicate<T> predicate)
		{
			return Array.FindAll(items, predicate);
		}

		public static bool IsNullOrEmpty(this IEnumerable @this)
		{
			return @this == null || !@this.GetEnumerator().MoveNext();
		}
	}
	[PublicAPI]
	public static class MathUtils
	{
		public const float Tolerance = 1E-06f;

		public static int Sqr(this int a)
		{
			return a * a;
		}

		public static long Sqr(this long a)
		{
			return a * a;
		}

		public static float Sqr(this float a)
		{
			return a * a;
		}

		public static double Sqr(this double a)
		{
			return a * a;
		}

		public static int Mod(int x, int m)
		{
			int num = x % m;
			return (num < 0) ? (num + m) : num;
		}

		public static byte ToByte(this float f)
		{
			f = ((f < 0f) ? 0f : ((f > 1f) ? 1f : f));
			return (byte)(f * 255f);
		}

		public static float ToFloat(this byte b)
		{
			return (float)(int)b / 255f;
		}

		public static string ToHexString(this byte[] ba)
		{
			StringBuilder stringBuilder = new StringBuilder(ba.Length * 2);
			foreach (byte b in ba)
			{
				stringBuilder.AppendFormat("{0:x2}", b);
			}
			return stringBuilder.ToString();
		}

		public static float Remap(this float value, float originalMin, float originalMax, float newMin, float newMax)
		{
			float num = Mathf.InverseLerp(originalMin, originalMax, value);
			return Mathf.Lerp(newMin, newMax, num);
		}
	}
	[PublicAPI]
	public static class ModUtils
	{
		public enum SpawnLocation
		{
			Outside,
			Vent
		}

		public struct EnemySpawnInfo
		{
			public readonly Type EnemyType;

			public readonly int Amount;

			public readonly SpawnLocation Location;

			public readonly bool ForceInside;

			public readonly bool ForceOutside;

			public EnemySpawnInfo(Type enemyType, int amount, SpawnLocation location, bool forceInside, bool forceOutside)
			{
				EnemyType = enemyType;
				Amount = amount;
				Location = location;
				ForceInside = forceInside;
				ForceOutside = forceOutside;
			}
		}

		public static MethodInfo SwitchToItemSlotMethod = typeof(PlayerControllerB).GetMethod("SwitchToItemSlot", BindingFlags.Instance | BindingFlags.NonPublic);

		public static MethodInfo GrabObjectServerRpcMethod = typeof(PlayerControllerB).GetMethod("GrabObjectServerRpc", BindingFlags.Instance | BindingFlags.NonPublic);

		public static MethodInfo GrabObjectClientRpcMethod = typeof(PlayerControllerB).GetMethod("GrabObjectClientRpc", BindingFlags.Instance | BindingFlags.NonPublic);

		public static FieldInfo GrabbedObjectValidatedField = typeof(PlayerControllerB).GetField("grabbedObjectValidated", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly int GrabValidated = Animator.StringToHash("GrabValidated");

		public static FieldInfo FloodLevelOffsetField = typeof(FloodWeather).GetField("floodLevelOffset", BindingFlags.Instance | BindingFlags.NonPublic);

		public static MethodInfo ThrowObjectServerRpcMethodInfo = typeof(PlayerControllerB).GetMethod("ThrowObjectServerRpc", BindingFlags.Instance | BindingFlags.NonPublic);

		public static MethodInfo SetSpecialGrabAnimationBoolMethodInfo = typeof(PlayerControllerB).GetMethod("SetSpecialGrabAnimationBool", BindingFlags.Instance | BindingFlags.NonPublic);

		public static FieldInfo ThrowingObjectFieldInfo = typeof(PlayerControllerB).GetField("throwingObject", BindingFlags.Instance | BindingFlags.NonPublic);

		public static void AddSpecificItemsForEvent(SelectableLevel newLevel, List<string> itemNames)
		{
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			SelectableLevel[] array = levels;
			foreach (SelectableLevel val in array)
			{
				foreach (SpawnableItemWithRarity item in val.spawnableScrap)
				{
					Item spawnableItem = item.spawnableItem;
					foreach (string itemName in itemNames)
					{
						if (spawnableItem.itemName.ToLower() == itemName && newLevel.spawnableScrap.All((SpawnableItemWithRarity s) => !string.Equals(s.spawnableItem.itemName, spawnableItem.itemName, StringComparison.CurrentCultureIgnoreCase)))
						{
							newLevel.spawnableScrap.Add(item);
							Plugin.Log.LogInfo((object)("Added event Item: " + item.spawnableItem.itemName));
						}
					}
				}
			}
		}

		public static void AddSpecificEnemiesForEvent(SelectableLevel newLevel, List<Type> enemyAITypes)
		{
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			SelectableLevel[] array = levels;
			foreach (SelectableLevel val in array)
			{
				foreach (SpawnableEnemyWithRarity enemy in val.Enemies)
				{
					GameObject enemyPrefab = enemy.enemyType.enemyPrefab;
					foreach (Type enemyAIType in enemyAITypes)
					{
						if ((Object)(object)enemyPrefab.GetComponent(enemyAIType) != (Object)null && newLevel.Enemies.All((SpawnableEnemyWithRarity e) => (Object)(object)e.enemyType.enemyPrefab != (Object)(object)enemyPrefab))
						{
							newLevel.Enemies.Add(enemy);
							Plugin.Log.LogInfo((object)("Added event Enemy: " + ((Object)enemy.enemyType.enemyPrefab).name));
						}
					}
				}
			}
		}

		public static void AddSpecificOutsideObjectsForEvent(SelectableLevel newLevel, List<string> outsideObjectNames)
		{
			SelectableLevel[] levels = StartOfRound.Instance.levels;
			SelectableLevel[] array = levels;
			foreach (SelectableLevel val in array)
			{
				SpawnableOutsideObjectWithRarity[] spawnableOutsideObjects = val.spawnableOutsideObjects;
				foreach (SpawnableOutsideObjectWithRarity val2 in spawnableOutsideObjects)
				{
					SpawnableOutsideObject spawnableObject = val2.spawnableObject;
					foreach (string outsideObjectName in outsideObjectNames)
					{
						if (((Object)spawnableObject.prefabToSpawn).name.ToLower() == outsideObjectName && newLevel.spawnableOutsideObjects.All((SpawnableOutsideObjectWithRarity s) => !string.Equals(((Object)s.spawnableObject.prefabToSpawn).name, ((Object)spawnableObject.prefabToSpawn).name, StringComparison.CurrentCultureIgnoreCase)))
						{
							newLevel.spawnableOutsideObjects = CollectionExtensions.AddToArray<SpawnableOutsideObjectWithRarity>(newLevel.spawnableOutsideObjects, val2);
							Plugin.Log.LogInfo((object)("Added event Outside Object: " + ((Object)val2.spawnableObject.prefabToSpawn).name));
						}
					}
				}
			}
		}

		public static GameObject FindEnemyPrefabByType(Type enemyType, List<SpawnableEnemyWithRarity> enemyList, SelectableLevel newLevel)
		{
			foreach (SpawnableEnemyWithRarity enemy in enemyList)
			{
				if ((Object)(object)enemy.enemyType.enemyPrefab.GetComponent(enemyType) != (Object)null)
				{
					return enemy.enemyType.enemyPrefab;
				}
			}
			AddSpecificEnemiesForEvent(newLevel, new List<Type> { enemyType });
			foreach (SpawnableEnemyWithRarity enemy2 in newLevel.Enemies)
			{
				if ((Object)(object)enemy2.enemyType.enemyPrefab.GetComponent(enemyType) != (Object)null)
				{
					return enemy2.enemyType.enemyPrefab;
				}
			}
			throw new Exception("Enemy type " + enemyType.Name + " not found and could not be added.");
		}

		public static EnemyAI SpawnEnemyOutside(Type enemyType, SelectableLevel level, bool forceOutside)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = ((!forceOutside) ? FindEnemyPrefabByType(enemyType, RoundManager.Instance.currentLevel.OutsideEnemies, level) : FindEnemyPrefabByType(enemyType, RoundManager.Instance.currentLevel.Enemies, level));
			GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode");
			Vector3 position = array[Random.Range(0, array.Length)].transform.position;
			GameObject val2 = Object.Instantiate<GameObject>(val, position, Quaternion.identity);
			val2.GetComponentInChildren<NetworkObject>().Spawn(true);
			EnemyAI component = val2.GetComponent<EnemyAI>();
			if (forceOutside)
			{
				component.enemyType.isOutsideEnemy = true;
				component.allAINodes = GameObject.FindGameObjectsWithTag("OutsideAINode");
				component.SyncPositionToClients();
			}
			RoundManager.Instance.SpawnedEnemies.Add(component);
			return component;
		}

		public static EnemyAI SpawnEnemyInside(Type enemyType, SelectableLevel level, bool forceInside)
		{
			//IL_0057: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = ((!forceInside) ? FindEnemyPrefabByType(enemyType, RoundManager.Instance.currentLevel.Enemies, level) : FindEnemyPrefabByType(enemyType, RoundManager.Instance.currentLevel.OutsideEnemies, level));
			int num = Random.Range(0, RoundManager.Instance.allEnemyVents.Length);
			Vector3 position = RoundManager.Instance.allEnemyVents[num].floorNode.position;
			Quaternion val2 = Quaternion.Euler(0f, RoundManager.Instance.allEnemyVents[num].floorNode.eulerAngles.y, 0f);
			GameObject val3 = Object.Instantiate<GameObject>(val, position, val2);
			val3.GetComponentInChildren<NetworkObject>().Spawn(true);
			EnemyAI component = val3.GetComponent<EnemyAI>();
			if (forceInside)
			{
				component.enemyType.isOutsideEnemy = false;
				component.allAINodes = GameObject.FindGameObjectsWithTag("AINode");
				component.SyncPositionToClients();
			}
			RoundManager.Instance.SpawnedEnemies.Add(component);
			return component;
		}

		public static EnemyAI SpawnEnemyOutside(Type enemyType, SelectableLevel level, bool forceOutside, Vector3 position)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = ((!forceOutside) ? FindEnemyPrefabByType(enemyType, RoundManager.Instance.currentLevel.OutsideEnemies, level) : FindEnemyPrefabByType(enemyType, RoundManager.Instance.currentLevel.Enemies, level));
			GameObject val2 = Object.Instantiate<GameObject>(val, position, Quaternion.identity);
			val2.GetComponentInChildren<NetworkObject>().Spawn(true);
			EnemyAI component = val2.GetComponent<EnemyAI>();
			if (forceOutside)
			{
				component.enemyType.isOutsideEnemy = true;
				component.allAINodes = GameObject.FindGameObjectsWithTag("OutsideAINode");
				component.SyncPositionToClients();
			}
			RoundManager.Instance.SpawnedEnemies.Add(component);
			return component;
		}

		public static EnemyAI SpawnEnemyInside(Type enemyType, SelectableLevel level, bool forceInside, Vector3 position)
		{
			//IL_005c: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = ((!forceInside) ? FindEnemyPrefabByType(enemyType, RoundManager.Instance.currentLevel.Enemies, level) : FindEnemyPrefabByType(enemyType, RoundManager.Instance.currentLevel.OutsideEnemies, level));
			int num = Random.Range(0, RoundManager.Instance.allEnemyVents.Length);
			Quaternion val2 = Quaternion.Euler(0f, RoundManager.Instance.allEnemyVents[num].floorNode.eulerAngles.y, 0f);
			GameObject val3 = Object.Instantiate<GameObject>(val, position, val2);
			val3.GetComponentInChildren<NetworkObject>().Spawn(true);
			EnemyAI component = val3.GetComponent<EnemyAI>();
			if (forceInside)
			{
				component.enemyType.isOutsideEnemy = false;
				component.allAINodes = GameObject.FindGameObjectsWithTag("AINode");
				component.SyncPositionToClients();
			}
			RoundManager.Instance.SpawnedEnemies.Add(component);
			return component;
		}

		public static EnemyAI SpawnEnemy(Type enemyType, SelectableLevel level, Vector3 position, bool isInside)
		{
			//IL_005c: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (isInside ? FindEnemyPrefabByType(enemyType, RoundManager.Instance.currentLevel.Enemies, level) : FindEnemyPrefabByType(enemyType, RoundManager.Instance.currentLevel.OutsideEnemies, level));
			int num = Random.Range(0, RoundManager.Instance.allEnemyVents.Length);
			Quaternion val2 = Quaternion.Euler(0f, RoundManager.Instance.allEnemyVents[num].floorNode.eulerAngles.y, 0f);
			GameObject val3 = Object.Instantiate<GameObject>(val, position, val2);
			val3.GetComponentInChildren<NetworkObject>().Spawn(true);
			EnemyAI component = val3.GetComponent<EnemyAI>();
			if (isInside)
			{
				component.enemyType.isOutsideEnemy = false;
				component.allAINodes = GameObject.FindGameObjectsWithTag("AINode");
				component.SyncPositionToClients();
			}
			else
			{
				component.enemyType.isOutsideEnemy = true;
				component.allAINodes = GameObject.FindGameObjectsWithTag("OutsideAINode");
				component.SyncPositionToClients();
			}
			RoundManager.Instance.SpawnedEnemies.Add(component);
			return component;
		}

		public static void SpawnMultipleEnemies(SelectableLevel level, List<EnemySpawnInfo> enemiesToSpawn)
		{
			foreach (EnemySpawnInfo item in enemiesToSpawn)
			{
				for (int i = 0; i < item.Amount; i++)
				{
					switch (item.Location)
					{
					case SpawnLocation.Outside:
						SpawnEnemyOutside(item.EnemyType, level, item.ForceOutside);
						break;
					case SpawnLocation.Vent:
						SpawnEnemyInside(item.EnemyType, level, item.ForceInside);
						break;
					}
				}
			}
		}

		public static int FirstEmptyItemSlot(this PlayerControllerB playerController)
		{
			int result = -1;
			if ((Object)(object)playerController.ItemSlots[playerController.currentItemSlot] == (Object)null)
			{
				result = playerController.currentItemSlot;
			}
			else
			{
				for (int i = 0; i < playerController.ItemSlots.Length; i++)
				{
					if ((Object)(object)playerController.ItemSlots[i] == (Object)null)
					{
						result = i;
						break;
					}
				}
			}
			return result;
		}

		public static void SwitchToItemSlot(this PlayerControllerB playerController, int slot, GrabbableObject grabbableObject = null)
		{
			SwitchToItemSlotMethod.Invoke(playerController, new object[2] { slot, grabbableObject });
		}

		public static void GrabObject(this PlayerControllerB playerController, NetworkObjectReference grabbedObjectRef)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			NetworkObject val = default(NetworkObject);
			((NetworkObjectReference)(ref grabbedObjectRef)).TryGet(ref val, NetworkManager.Singleton);
			GrabbableObject component = ((Component)val).GetComponent<GrabbableObject>();
			GrabObjectServerRpcMethod.Invoke(playerController, new object[1] { grabbedObjectRef });
			GrabbedObjectValidatedField.SetValue(playerController, true);
			playerController.currentlyHeldObjectServer = component;
			playerController.currentlyHeldObjectServer.GrabItemOnClient();
			playerController.isHoldingObject = true;
			playerController.playerBodyAnimator.SetBool(GrabValidated, true);
			GrabObjectClientRpcMethod.Invoke(playerController, new object[2] { true, grabbedObjectRef });
		}

		public static float GetFloodLevelOffset(this FloodWeather weather)
		{
			return (float)FloodLevelOffsetField.GetValue(weather);
		}

		public static void ThrowObjectServerRpc(this PlayerControllerB playerController, NetworkObjectReference grabbedObject, bool droppedInElevator, bool droppedInShipRoom, Vector3 targetFloorPosition, int floorYRot)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			ThrowObjectServerRpcMethodInfo.Invoke(playerController, new object[5] { grabbedObject, droppedInElevator, droppedInShipRoom, targetFloorPosition, floorYRot });
		}

		public static void SetSpecialGrabAnimationBool(this PlayerControllerB playerController, bool setTrue, GrabbableObject currentItem = null)
		{
			SetSpecialGrabAnimationBoolMethodInfo.Invoke(playerController, new object[2] { setTrue, currentItem });
		}

		public static void SetThrowingObject(this PlayerControllerB playerController, bool throwingObject)
		{
			ThrowingObjectFieldInfo.SetValue(playerController, throwingObject);
		}
	}
	public static class SoundUtils
	{
		public static List<AudioClip> GetAllSFX(this EnemyAI enemyAI)
		{
			List<AudioClip> list = new List<AudioClip>();
			BaboonBirdAI val = (BaboonBirdAI)(object)((enemyAI is BaboonBirdAI) ? enemyAI : null);
			if (val == null)
			{
				BlobAI val2 = (BlobAI)(object)((enemyAI is BlobAI) ? enemyAI : null);
				if (val2 == null)
				{
					CentipedeAI val3 = (CentipedeAI)(object)((enemyAI is CentipedeAI) ? enemyAI : null);
					if (val3 == null)
					{
						CrawlerAI val4 = (CrawlerAI)(object)((enemyAI is CrawlerAI) ? enemyAI : null);
						if (val4 == null)
						{
							DoublewingAI val5 = (DoublewingAI)(object)((enemyAI is DoublewingAI) ? enemyAI : null);
							if (val5 == null)
							{
								DressGirlAI val6 = (DressGirlAI)(object)((enemyAI is DressGirlAI) ? enemyAI : null);
								if (val6 == null)
								{
									FlowermanAI val7 = (FlowermanAI)(object)((enemyAI is FlowermanAI) ? enemyAI : null);
									if (val7 == null)
									{
										HoarderBugAI val8 = (HoarderBugAI)(object)((enemyAI is HoarderBugAI) ? enemyAI : null);
										if (val8 == null)
										{
											JesterAI val9 = (JesterAI)(object)((enemyAI is JesterAI) ? enemyAI : null);
											if (val9 == null)
											{
												MouthDogAI val10 = (MouthDogAI)(object)((enemyAI is MouthDogAI) ? enemyAI : null);
												if (val10 == null)
												{
													NutcrackerEnemyAI val11 = (NutcrackerEnemyAI)(object)((enemyAI is NutcrackerEnemyAI) ? enemyAI : null);
													if (val11 == null)
													{
														PufferAI val12 = (PufferAI)(object)((enemyAI is PufferAI) ? enemyAI : null);
														if (val12 == null)
														{
															SandSpiderAI val13 = (SandSpiderAI)(object)((enemyAI is SandSpiderAI) ? enemyAI : null);
															if (val13 == null)
															{
																SandWormAI val14 = (SandWormAI)(object)((enemyAI is SandWormAI) ? enemyAI : null);
																if (val14 == null)
																{
																	SpringManAI val15 = (SpringManAI)(object)((enemyAI is SpringManAI) ? enemyAI : null);
																	if (val15 != null)
																	{
																		list.AddRange(val15.springNoises);
																	}
																}
																else
																{
																	list.AddRange(val14.groundRumbleSFX);
																	list.AddRange(val14.ambientRumbleSFX);
																	list.Add(val14.hitGroundSFX);
																	list.Add(val14.emergeFromGroundSFX);
																	list.AddRange(val14.roarSFX);
																}
															}
															else
															{
																list.AddRange(val13.footstepSFX);
																list.Add(val13.hitWebSFX);
																list.Add(val13.attackSFX);
																list.Add(val13.spoolPlayerSFX);
																list.Add(val13.hangPlayerSFX);
																list.Add(val13.breakWebSFX);
																list.Add(val13.hitSpiderSFX);
															}
														}
														else
														{
															list.AddRange(val12.footstepsSFX);
															list.AddRange(val12.frightenSFX);
															list.Add(val12.stomp);
															list.Add(val12.angry);
															list.Add(val12.puff);
															list.Add(val12.nervousMumbling);
															list.Add(val12.rattleTail);
															list.Add(val12.bitePlayerSFX);
														}
													}
													else
													{
														list.AddRange(val11.torsoFinishTurningClips);
														list.Add(val11.aimSFX);
														list.Add(val11.kickSFX);
													}
												}
												else
												{
													list.Add(val10.screamSFX);
													list.Add(val10.breathingSFX);
													list.Add(val10.killPlayerSFX);
												}
											}
											else
											{
												list.Add(val9.popGoesTheWeaselTheme);
												list.Add(val9.popUpSFX);
												list.Add(val9.screamingSFX);
												list.Add(val9.killPlayerSFX);
											}
										}
										else
										{
											list.AddRange(val8.chitterSFX);
											list.AddRange(val8.angryScreechSFX);
											list.Add(val8.angryVoiceSFX);
											list.Add(val8.bugFlySFX);
											list.Add(val8.hitPlayerSFX);
										}
									}
									else
									{
										list.Add(val7.crackNeckSFX);
									}
								}
								else
								{
									list.AddRange(val6.appearStaringSFX);
									list.Add(val6.skipWalkSFX);
									list.Add(val6.breathingSFX);
								}
							}
							else
							{
								list.AddRange(val5.birdScreechSFX);
								list.Add(val5.birdHitGroundSFX);
							}
						}
						else
						{
							list.Add(val4.shortRoar);
							list.AddRange(val4.hitWallSFX);
							list.AddRange(val4.hitCrawlerSFX);
							list.Add(val4.bitePlayerSFX);
							list.Add(val4.eatPlayerSFX);
							list.AddRange(val4.hitCrawlerSFX);
							list.AddRange(val4.longRoarSFX);
						}
					}
					else
					{
						list.Add(val3.fallShriek);
						list.Add(val3.hitGroundSFX);
						list.Add(val3.hitCentipede);
						list.AddRange(val3.shriekClips);
						list.Add(val3.clingToPlayer3D);
					}
				}
				else
				{
					list.Add(val2.agitatedSFX);
					list.Add(val2.jiggleSFX);
					list.Add(val2.hitSlimeSFX);
					list.Add(val2.killPlayerSFX);
					list.Add(val2.idleSFX);
				}
			}
			else
			{
				list.AddRange(val.cawLaughSFX);
				list.AddRange(val.cawScreamSFX);
				list.AddRange(val.cawScreamSFX);
			}
			return list;
		}
	}
	public static class TerminalUtils
	{
	}
	public class Timing : MonoBehaviour
	{
		private struct ProcessIndex : IEquatable<ProcessIndex>
		{
			public Segment seg;

			public int i;

			public bool Equals(ProcessIndex other)
			{
				return seg == other.seg && i == other.i;
			}

			public override bool Equals(object other)
			{
				if (other is ProcessIndex)
				{
					return Equals((ProcessIndex)other);
				}
				return false;
			}

			public static bool operator ==(ProcessIndex a, ProcessIndex b)
			{
				return a.seg == b.seg && a.i == b.i;
			}

			public static bool operator !=(ProcessIndex a, ProcessIndex b)
			{
				return a.seg != b.seg || a.i != b.i;
			}

			public override int GetHashCode()
			{
				return (int)(seg - 2) * 715827882 + i;
			}
		}

		[Tooltip("How quickly the SlowUpdate segment ticks.")]
		public float TimeBetweenSlowUpdateCalls = 1f / 7f;

		[Tooltip("How much data should be sent to the profiler window when it's open.")]
		public DebugInfoType ProfilerDebugAmount;

		[Tooltip("A count of the number of Update coroutines that are currently running.")]
		[Space(12f)]
		public int UpdateCoroutines;

		[Tooltip("A count of the number of FixedUpdate coroutines that are currently running.")]
		public int FixedUpdateCoroutines;

		[Tooltip("A count of the number of LateUpdate coroutines that are currently running.")]
		public int LateUpdateCoroutines;

		[Tooltip("A count of the number of SlowUpdate coroutines that are currently running.")]
		public int SlowUpdateCoroutines;

		[NonSerialized]
		public float localTime;

		[NonSerialized]
		public float deltaTime;

		public static Func<IEnumerator<float>, CoroutineHandle, IEnumerator<float>> ReplacementFunction;

		public const float WaitForOneFrame = float.NegativeInfinity;

		private static object _tmpRef;

		private static bool _tmpBool;

		private static CoroutineHandle _tmpHandle;

		private int _currentUpdateFrame;

		private int _currentLateUpdateFrame;

		private int _currentSlowUpdateFrame;

		private int _nextUpdateProcessSlot;

		private int _nextLateUpdateProcessSlot;

		private int _nextFixedUpdateProcessSlot;

		private int _nextSlowUpdateProcessSlot;

		private int _lastUpdateProcessSlot;

		private int _lastLateUpdateProcessSlot;

		private int _lastFixedUpdateProcessSlot;

		private int _lastSlowUpdateProcessSlot;

		private float _lastUpdateTime;

		private float _lastLateUpdateTime;

		private float _lastFixedUpdateTime;

		private float _lastSlowUpdateTime;

		private float _lastSlowUpdateDeltaTime;

		private ushort _framesSinceUpdate;

		private ushort _expansions = 1;

		[SerializeField]
		[HideInInspector]
		private byte _instanceID;

		private readonly Dictionary<CoroutineHandle, HashSet<CoroutineHandle>> _waitingTriggers = new Dictionary<CoroutineHandle, HashSet<CoroutineHandle>>();

		private readonly HashSet<CoroutineHandle> _allWaiting = new HashSet<CoroutineHandle>();

		private readonly Dictionary<CoroutineHandle, ProcessIndex> _handleToIndex = new Dictionary<CoroutineHandle, ProcessIndex>();

		private readonly Dictionary<ProcessIndex, CoroutineHandle> _indexToHandle = new Dictionary<ProcessIndex, CoroutineHandle>();

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

		private readonly Dictionary<string, HashSet<CoroutineHandle>> _taggedProcesses = new Dictionary<string, HashSet<CoroutineHandle>>();

		private IEnumerator<float>[] UpdateProcesses = new IEnumerator<float>[256];

		private IEnumerator<float>[] LateUpdateProcesses = new IEnumerator<float>[8];

		private IEnumerator<float>[] FixedUpdateProcesses = new IEnumerator<float>[64];

		private IEnumerator<float>[] SlowUpdateProcesses = new IEnumerator<float>[64];

		private bool[] UpdatePaused = new bool[256];

		private bool[] LateUpdatePaused = new bool[8];

		private bool[] FixedUpdatePaused = new bool[64];

		private bool[] SlowUpdatePaused = new bool[64];

		private bool[] UpdateHeld = new bool[256];

		private bool[] LateUpdateHeld = new bool[8];

		private bool[] FixedUpdateHeld = new bool[64];

		private bool[] SlowUpdateHeld = new bool[64];

		private const ushort FramesUntilMaintenance = 64;

		private const int ProcessArrayChunkSize = 64;

		private const int InitialBufferSizeLarge = 256;

		private const int InitialBufferSizeMedium = 64;

		private const int InitialBufferSizeSmall = 8;

		private static Timing[] ActiveInstances = new Timing[16];

		private static Timing _instance;

		public static float LocalTime => Instance.localTime;

		public static float DeltaTime => Instance.deltaTime;

		public static Thread MainThread { get; private set; }

		public static CoroutineHandle CurrentCoroutine
		{
			get
			{
				for (int i = 0; i < ActiveInstances.Length; i++)
				{
					if ((Object)(object)ActiveInstances[i] != (Object)null && ActiveInstances[i].currentCoroutine.IsValid)
					{
						return ActiveInstances[i].currentCoroutine;
					}
				}
				return default(CoroutineHandle);
			}
		}

		public CoroutineHandle currentCoroutine { get; private set; }

		public static Timing Instance
		{
			get
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Expected O, but got Unknown
				if ((Object)(object)_instance == (Object)null || !Object.op_Implicit((Object)(object)((Component)_instance).gameObject))
				{
					GameObject val = GameObject.Find("Timing Controller");
					if ((Object)(object)val == (Object)null)
					{
						val = new GameObject
						{
							name = "Timing Controller"
						};
						Object.DontDestroyOnLoad((Object)(object)val);
					}
					_instance = val.GetComponent<Timing>() ?? val.AddComponent<Timing>();
					_instance.InitializeInstanceID();
				}
				return _instance;
			}
			set
			{
				_instance = value;
			}
		}

		public static event Action OnPreExecute;

		public event Action<Exception, string> OnException;

		private void OnDestroy()
		{
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
		}

		private void OnEnable()
		{
			if (MainThread == null)
			{
				MainThread = Thread.CurrentThread;
			}
			InitializeInstanceID();
		}

		private void OnDisable()
		{
			if (_instanceID < ActiveInstances.Length)
			{
				ActiveInstances[_instanceID] = null;
			}
		}

		private void InvokeException(Exception e, string name)
		{
			try
			{
				this.OnException(e, name);
			}
			catch (Exception)
			{
			}
		}

		private void InitializeInstanceID()
		{
			if (!((Object)(object)ActiveInstances[_instanceID] == (Object)null))
			{
				return;
			}
			if (_instanceID == 0)
			{
				_instanceID++;
			}
			while (_instanceID <= 16)
			{
				if (_instanceID == 16)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
					throw new OverflowException("You are only allowed 15 different contexts for MEC to run inside at one time.");
				}
				if ((Object)(object)ActiveInstances[_instanceID] == (Object)null)
				{
					ActiveInstances[_instanceID] = this;
					break;
				}
				_instanceID++;
			}
		}

		private void Update()
		{
			if (Timing.OnPreExecute != null)
			{
				Timing.OnPreExecute();
			}
			if (_lastSlowUpdateTime + TimeBetweenSlowUpdateCalls < Time.realtimeSinceStartup && _nextSlowUpdateProcessSlot > 0)
			{
				ProcessIndex processIndex = default(ProcessIndex);
				processIndex.seg = Segment.SlowUpdate;
				ProcessIndex key = processIndex;
				if (UpdateTimeValues(key.seg))
				{
					_lastSlowUpdateProcessSlot = _nextSlowUpdateProcessSlot;
				}
				key.i = 0;
				while (key.i < _lastSlowUpdateProcessSlot)
				{
					string name = "Unknown";
					try
					{
						if (!SlowUpdatePaused[key.i] && !SlowUpdateHeld[key.i] && SlowUpdateProcesses[key.i] != null && !(localTime < SlowUpdateProcesses[key.i].Current))
						{
							currentCoroutine = _indexToHandle[key];
							name = _taggedProcesses.FirstOrDefault((KeyValuePair<string, HashSet<CoroutineHandle>> x) => x.Value.Any((CoroutineHandle handle) => handle == currentCoroutine)).Key ?? "Unknown";
							if (ProfilerDebugAmount == DebugInfoType.None || _indexToHandle.ContainsKey(key))
							{
							}
							if (!SlowUpdateProcesses[key.i].MoveNext())
							{
								if (_indexToHandle.ContainsKey(key))
								{
									KillCoroutinesOnInstance(_indexToHandle[key]);
								}
							}
							else if (SlowUpdateProcesses[key.i] != null && float.IsNaN(SlowUpdateProcesses[key.i].Current))
							{
								if (ReplacementFunction != null)
								{
									SlowUpdateProcesses[key.i] = ReplacementFunction(SlowUpdateProcesses[key.i], _indexToHandle[key]);
									ReplacementFunction = null;
								}
								key.i--;
							}
							if (ProfilerDebugAmount == DebugInfoType.None)
							{
							}
						}
					}
					catch (Exception ex)
					{
						InvokeException(ex, name);
						if (ex is MissingReferenceException)
						{
							Debug.LogError((object)"This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\nExample: Timing.RunCoroutine(_foo().CancelWith(gameObject), Segment.SlowUpdate);");
						}
					}
					key.i++;
				}
			}
			if (_nextUpdateProcessSlot > 0)
			{
				ProcessIndex processIndex = default(ProcessIndex);
				processIndex.seg = Segment.Update;
				ProcessIndex key2 = processIndex;
				if (UpdateTimeValues(key2.seg))
				{
					_lastUpdateProcessSlot = _nextUpdateProcessSlot;
				}
				key2.i = 0;
				while (key2.i < _lastUpdateProcessSlot)
				{
					string name2 = string.Empty;
					try
					{
						if (!UpdatePaused[key2.i] && !UpdateHeld[key2.i] && UpdateProcesses[key2.i] != null && !(localTime < UpdateProcesses[key2.i].Current))
						{
							currentCoroutine = _indexToHandle[key2];
							name2 = _taggedProcesses.FirstOrDefault((KeyValuePair<string, HashSet<CoroutineHandle>> x) => x.Value.Any((CoroutineHandle handle) => handle == currentCoroutine)).Key ?? "Unknown";
							if (ProfilerDebugAmount == DebugInfoType.None || _indexToHandle.ContainsKey(key2))
							{
							}
							if (!UpdateProcesses[key2.i].MoveNext())
							{
								if (_indexToHandle.ContainsKey(key2))
								{
									KillCoroutinesOnInstance(_indexToHandle[key2]);
								}
							}
							else if (UpdateProcesses[key2.i] != null && float.IsNaN(UpdateProcesses[key2.i].Current))
							{
								if (ReplacementFunction != null)
								{
									UpdateProcesses[key2.i] = ReplacementFunction(UpdateProcesses[key2.i], _indexToHandle[key2]);
									ReplacementFunction = null;
								}
								key2.i--;
							}
							if (ProfilerDebugAmount == DebugInfoType.None)
							{
							}
						}
					}
					catch (Exception ex2)
					{
						InvokeException(ex2, name2);
						if (ex2 is MissingReferenceException)
						{
							Debug.LogError((object)"This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\nExample: Timing.RunCoroutine(_foo().CancelWith(gameObject));");
						}
					}
					key2.i++;
				}
			}
			currentCoroutine = default(CoroutineHandle);
			if (++_framesSinceUpdate > 64)
			{
				_framesSinceUpdate = 0;
				if (ProfilerDebugAmount != 0)
				{
				}
				RemoveUnused();
				if (ProfilerDebugAmount == DebugInfoType.None)
				{
				}
			}
		}

		private void FixedUpdate()
		{
			if (Timing.OnPreExecute != null)
			{
				Timing.OnPreExecute();
			}
			if (_nextFixedUpdateProcessSlot <= 0)
			{
				return;
			}
			ProcessIndex processIndex = default(ProcessIndex);
			processIndex.seg = Segment.FixedUpdate;
			ProcessIndex key = processIndex;
			if (UpdateTimeValues(key.seg))
			{
				_lastFixedUpdateProcessSlot = _nextFixedUpdateProcessSlot;
			}
			key.i = 0;
			while (key.i < _lastFixedUpdateProcessSlot)
			{
				string name = string.Empty;
				try
				{
					if (!FixedUpdatePaused[key.i] && !FixedUpdateHeld[key.i] && FixedUpdateProcesses[key.i] != null && !(localTime < FixedUpdateProcesses[key.i].Current))
					{
						currentCoroutine = _indexToHandle[key];
						name = _taggedProcesses.FirstOrDefault((KeyValuePair<string, HashSet<CoroutineHandle>> x) => x.Value.Any((CoroutineHandle handle) => handle == currentCoroutine)).Key ?? "Unknown";
						if (ProfilerDebugAmount == DebugInfoType.None || _indexToHandle.ContainsKey(key))
						{
						}
						if (!FixedUpdateProcesses[key.i].MoveNext())
						{
							if (_indexToHandle.ContainsKey(key))
							{
								KillCoroutinesOnInstance(_indexToHandle[key]);
							}
						}
						else if (FixedUpdateProcesses[key.i] != null && float.IsNaN(FixedUpdateProcesses[key.i].Current))
						{
							if (ReplacementFunction != null)
							{
								FixedUpdateProcesses[key.i] = ReplacementFunction(FixedUpdateProcesses[key.i], _indexToHandle[key]);
								ReplacementFunction = null;
							}
							key.i--;
						}
						if (ProfilerDebugAmount == DebugInfoType.None)
						{
						}
					}
				}
				catch (Exception ex)
				{
					InvokeException(ex, name);
					if (ex is MissingReferenceException)
					{
						Debug.LogError((object)"This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\nExample: Timing.RunCoroutine(_foo().CancelWith(gameObject), Segment.FixedUpdate);");
					}
				}
				key.i++;
			}
			currentCoroutine = default(CoroutineHandle);
		}

		private void LateUpdate()
		{
			if (Timing.OnPreExecute != null)
			{
				Timing.OnPreExecute();
			}
			if (_nextLateUpdateProcessSlot <= 0)
			{
				return;
			}
			ProcessIndex processIndex = default(ProcessIndex);
			processIndex.seg = Segment.LateUpdate;
			ProcessIndex key = processIndex;
			if (UpdateTimeValues(key.seg))
			{
				_lastLateUpdateProcessSlot = _nextLateUpdateProcessSlot;
			}
			key.i = 0;
			while (key.i < _lastLateUpdateProcessSlot)
			{
				string name = string.Empty;
				try
				{
					if (!LateUpdatePaused[key.i] && !LateUpdateHeld[key.i] && LateUpdateProcesses[key.i] != null && !(localTime < LateUpdateProcesses[key.i].Current))
					{
						currentCoroutine = _indexToHandle[key];
						name = _taggedProcesses.FirstOrDefault((KeyValuePair<string, HashSet<CoroutineHandle>> x) => x.Value.Any((CoroutineHandle handle) => handle == currentCoroutine)).Key ?? "Unknown";
						if (ProfilerDebugAmount == DebugInfoType.None || _indexToHandle.ContainsKey(key))
						{
						}
						if (!LateUpdateProcesses[key.i].MoveNext())
						{
							if (_indexToHandle.ContainsKey(key))
							{
								KillCoroutinesOnInstance(_indexToHandle[key]);
							}
						}
						else if (LateUpdateProcesses[key.i] != null && float.IsNaN(LateUpdateProcesses[key.i].Current))
						{
							if (ReplacementFunction != null)
							{
								LateUpdateProcesses[key.i] = ReplacementFunction(LateUpdateProcesses[key.i], _indexToHandle[key]);
								ReplacementFunction = null;
							}
							key.i--;
						}
						if (ProfilerDebugAmount == DebugInfoType.None)
						{
						}
					}
				}
				catch (Exception ex)
				{
					InvokeException(ex, name);
					if (ex is MissingReferenceException)
					{
						Debug.LogError((object)"This exception can probably be fixed by adding \"CancelWith(gameObject)\" when you run the coroutine.\nExample: Timing.RunCoroutine(_foo().CancelWith(gameObject), Segment.LateUpdate);");
					}
				}
				key.i++;
			}
			currentCoroutine = default(CoroutineHandle);
		}

		private void RemoveUnused()
		{
			Dictionary<CoroutineHandle, HashSet<CoroutineHandle>>.Enumerator enumerator = _waitingTriggers.GetEnumerator();
			while (enumerator.MoveNext())
			{
				if (enumerator.Current.Value.Count == 0)
				{
					_waitingTriggers.Remove(enumerator.Current.Key);
					enumerator = _waitingTriggers.GetEnumerator();
				}
				else if (_handleToIndex.ContainsKey(enumerator.Current.Key) && CoindexIsNull(_handleToIndex[enumerator.Current.Key]))
				{
					CloseWaitingProcess(enumerator.Current.Key);
					enumerator = _waitingTriggers.GetEnumerator();
				}
			}
			ProcessIndex key = default(ProcessIndex);
			ProcessIndex processIndex = default(ProcessIndex);
			key.seg = (processIndex.seg = Segment.Update);
			key.i = (processIndex.i = 0);
			while (key.i < _nextUpdateProcessSlot)
			{
				if (UpdateProcesses[key.i] != null)
				{
					if (key.i != processIndex.i)
					{
						UpdateProcesses[processIndex.i] = UpdateProcesses[key.i];
						UpdatePaused[processIndex.i] = UpdatePaused[key.i];
						UpdateHeld[processIndex.i] = UpdateHeld[key.i];
						if (_indexToHandle.ContainsKey(processIndex))
						{
							RemoveTag(_indexToHandle[processIndex]);
							_handleToIndex.Remove(_indexToHandle[processIndex]);
							_indexToHandle.Remove(processIndex);
						}
						_handleToIndex[_indexToHandle[key]] = processIndex;
						_indexToHandle.Add(processIndex, _indexToHandle[key]);
						_indexToHandle.Remove(key);
					}
					processIndex.i++;
				}
				key.i++;
			}
			key.i = processIndex.i;
			while (key.i < _nextUpdateProcessSlot)
			{
				UpdateProcesses[key.i] = null;
				UpdatePaused[key.i] = false;
				UpdateHeld[key.i] = false;
				if (_indexToHandle.ContainsKey(key))
				{
					RemoveTag(_indexToHandle[key]);
					_handleToIndex.Remove(_indexToHandle[key]);
					_indexToHandle.Remove(key);
				}
				key.i++;
			}
			_lastUpdateProcessSlot -= _nextUpdateProcessSlot - processIndex.i;
			UpdateCoroutines = (_nextUpdateProcessSlot = processIndex.i);
			key.seg = (processIndex.seg = Segment.FixedUpdate);
			key.i = (processIndex.i = 0);
			while (key.i < _nextFixedUpdateProcessSlot)
			{
				if (FixedUpdateProcesses[key.i] != null)
				{
					if (key.i != processIndex.i)
					{
						FixedUpdateProcesses[processIndex.i] = FixedUpdateProcesses[key.i];
						FixedUpdatePaused[processIndex.i] = FixedUpdatePaused[key.i];
						FixedUpdateHeld[processIndex.i] = FixedUpdateHeld[key.i];
						if (_indexToHandle.ContainsKey(processIndex))
						{
							RemoveTag(_indexToHandle[processIndex]);
							_handleToIndex.Remove(_indexToHandle[processIndex]);
							_indexToHandle.Remove(processIndex);
						}
						_handleToIndex[_indexToHandle[key]] = processIndex;
						_indexToHandle.Add(processIndex, _indexToHandle[key]);
						_indexToHandle.Remove(key);
					}
					processIndex.i++;
				}
				key.i++;
			}
			key.i = processIndex.i;
			while (key.i < _nextFixedUpdateProcessSlot)
			{
				FixedUpdateProcesses[key.i] = null;
				FixedUpdatePaused[key.i] = false;
				FixedUpdateHeld[key.i] = false;
				if (_indexToHandle.ContainsKey(key))
				{
					RemoveTag(_indexToHandle[key]);
					_handleToIndex.Remove(_indexToHandle[key]);
					_indexToHandle.Remove(key);
				}
				key.i++;
			}
			_lastFixedUpdateProcessSlot -= _nextFixedUpdateProcessSlot - processIndex.i;
			FixedUpdateCoroutines = (_nextFixedUpdateProcessSlot = processIndex.i);
			key.seg = (processIndex.seg = Segment.LateUpdate);
			key.i = (processIndex.i = 0);
			while (key.i < _nextLateUpdateProcessSlot)
			{
				if (LateUpdateProcesses[key.i] != null)
				{
					if (key.i != processIndex.i)
					{
						LateUpdateProcesses[processIndex.i] = LateUpdateProcesses[key.i];
						LateUpdatePaused[processIndex.i] = LateUpdatePaused[key.i];
						LateUpdateHeld[processIndex.i] = LateUpdateHeld[key.i];
						if (_indexToHandle.ContainsKey(processIndex))
						{
							RemoveTag(_indexToHandle[processIndex]);
							_handleToIndex.Remove(_indexToHandle[processIndex]);
							_indexToHandle.Remove(processIndex);
						}
						_handleToIndex[_indexToHandle[key]] = processIndex;
						_indexToHandle.Add(processIndex, _indexToHandle[key]);
						_indexToHandle.Remove(key);
					}
					processIndex.i++;
				}
				key.i++;
			}
			key.i = processIndex.i;
			while (key.i < _nextLateUpdateProcessSlot)
			{
				LateUpdateProcesses[key.i] = null;
				LateUpdatePaused[key.i] = false;
				LateUpdateHeld[key.i] = false;
				if (_indexToHandle.ContainsKey(key))
				{
					RemoveTag(_indexToHandle[key]);
					_handleToIndex.Remove(_indexToHandle[key]);
					_indexToHandle.Remove(key);
				}
				key.i++;
			}
			_lastLateUpdateProcessSlot -= _nextLateUpdateProcessSlot - processIndex.i;
			LateUpdateCoroutines = (_nextLateUpdateProcessSlot = processIndex.i);
			key.seg = (processIndex.seg = Segment.SlowUpdate);
			key.i = (processIndex.i = 0);
			while (key.i < _nextSlowUpdateProcessSlot)
			{
				if (SlowUpdateProcesses[key.i] != null)
				{
					if (key.i != processIndex.i)
					{
						SlowUpdateProcesses[processIndex.i] = SlowUpdateProcesses[key.i];
						SlowUpdatePaused[processIndex.i] = SlowUpdatePaused[key.i];
						SlowUpdateHeld[processIndex.i] = SlowUpdateHeld[key.i];
						if (_indexToHandle.ContainsKey(processIndex))
						{
							RemoveTag(_indexToHandle[processIndex]);
							_handleToIndex.Remove(_indexToHandle[processIndex]);
							_indexToHandle.Remove(processIndex);
						}
						_handleToIndex[_indexToHandle[key]] = processIndex;
						_indexToHandle.Add(processIndex, _indexToHandle[key]);
						_indexToHandle.Remove(key);
					}
					processIndex.i++;
				}
				key.i++;
			}
			key.i = processIndex.i;
			while (key.i < _nextSlowUpdateProcessSlot)
			{
				SlowUpdateProcesses[key.i] = null;
				SlowUpdatePaused[key.i] = false;
				SlowUpdateHeld[key.i] = false;
				if (_indexToHandle.ContainsKey(key))
				{
					RemoveTag(_indexToHandle[key]);
					_handleToIndex.Remove(_indexToHandle[key]);
					_indexToHandle.Remove(key);
				}
				key.i++;
			}
			_lastSlowUpdateProcessSlot -= _nextSlowUpdateProcessSlot - processIndex.i;
			SlowUpdateCoroutines = (_nextSlowUpdateProcessSlot = processIndex.i);
		}

		public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine)
		{
			return (coroutine == null) ? default(CoroutineHandle) : Instance.RunCoroutineInternal(coroutine, Segment.Update, null, new CoroutineHandle(Instance._instanceID), prewarm: true);
		}

		public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, string tag)
		{
			return (coroutine == null) ? default(CoroutineHandle) : Instance.RunCoroutineInternal(coroutine, Segment.Update, tag, new CoroutineHandle(Instance._instanceID), prewarm: true);
		}

		public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment segment)
		{
			return (coroutine == null) ? default(CoroutineHandle) : Instance.RunCoroutineInternal(coroutine, segment, null, new CoroutineHandle(Instance._instanceID), prewarm: true);
		}

		public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment segment, string tag)
		{
			return (coroutine == null) ? default(CoroutineHandle) : Instance.RunCoroutineInternal(coroutine, segment, tag, new CoroutineHandle(Instance._instanceID), prewarm: true);
		}

		public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine)
		{
			return (coroutine == null) ? default(CoroutineHandle) : RunCoroutineInternal(coroutine, Segment.Update, null, new CoroutineHandle(_instanceID), prewarm: true);
		}

		public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, string tag)
		{
			return (coroutine == null) ? default(CoroutineHandle) : RunCoroutineInternal(coroutine, Segment.Update, tag, new CoroutineHandle(_instanceID), prewarm: true);
		}

		public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment segment)
		{
			return (coroutine == null) ? default(CoroutineHandle) : RunCoroutineInternal(coroutine, segment, null, new CoroutineHandle(_instanceID), prewarm: true);
		}

		public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment segment, string tag)
		{
			return (coroutine == null) ? default(CoroutineHandle) : RunCoroutineInternal(coroutine, segment, tag, new CoroutineHandle(_instanceID), prewarm: true);
		}

		private CoroutineHandle RunCoroutineInternal(IEnumerator<float> coroutine, Segment segment, string tag, CoroutineHandle handle, bool prewarm)
		{
			ProcessIndex processIndex = default(ProcessIndex);
			processIndex.seg = segment;
			ProcessIndex processIndex2 = processIndex;
			if (_handleToIndex.ContainsKey(handle))
			{
				_indexToHandle.Remove(_handleToIndex[handle]);
				_handleToIndex.Remove(handle);
			}
			float num = localTime;
			float num2 = deltaTime;
			CoroutineHandle coroutineHandle = currentCoroutine;
			currentCoroutine = handle;
			switch (segment)
			{
			case Segment.Update:
				if (_nextUpdateProcessSlot >= UpdateProcesses.Length)
				{
					IEnumerator<float>[] updateProcesses = UpdateProcesses;
					bool[] updatePaused = UpdatePaused;
					bool[] updateHeld = UpdateHeld;
					UpdateProcesses = new IEnumerator<float>[UpdateProcesses.Length + 64 * _expansions++];
					UpdatePaused = new bool[UpdateProcesses.Length];
					UpdateHeld = new bool[UpdateProcesses.Length];
					for (int k = 0; k < updateProcesses.Length; k++)
					{
						UpdateProcesses[k] = updateProcesses[k];
						UpdatePaused[k] = updatePaused[k];
						UpdateHeld[k] = updateHeld[k];
					}
				}
				if (UpdateTimeValues(processIndex2.seg))
				{
					_lastUpdateProcessSlot = _nextUpdateProcessSlot;
				}
				processIndex2.i = _nextUpdateProcessSlot++;
				UpdateProcesses[processIndex2.i] = coroutine;
				if (tag != null)
				{
					AddTag(tag, handle);
				}
				_indexToHandle.Add(processIndex2, handle);
				_handleToIndex.Add(handle, processIndex2);
				while (prewarm)
				{
					if (!UpdateProcesses[processIndex2.i].MoveNext())
					{
						if (_indexToHandle.ContainsKey(processIndex2))
						{
							KillCoroutinesOnInstance(_indexToHandle[processIndex2]);
						}
						prewarm = false;
					}
					else if (UpdateProcesses[processIndex2.i] != null && float.IsNaN(UpdateProcesses[processIndex2.i].Current))
					{
						if (ReplacementFunction != null)
						{
							UpdateProcesses[processIndex2.i] = ReplacementFunction(UpdateProcesses[processIndex2.i], _indexToHandle[processIndex2]);
							ReplacementFunction = null;
						}
						prewarm = !UpdatePaused[processIndex2.i] && !UpdateHeld[processIndex2.i];
					}
					else
					{
						prewarm = false;
					}
				}
				break;
			case Segment.FixedUpdate:
				if (_nextFixedUpdateProcessSlot >= FixedUpdateProcesses.Length)
				{
					IEnumerator<float>[] fixedUpdateProcesses = FixedUpdateProcesses;
					bool[] fixedUpdatePaused = FixedUpdatePaused;
					bool[] fixedUpdateHeld = FixedUpdateHeld;
					FixedUpdateProcesses = new IEnumerator<float>[FixedUpdateProcesses.Length + 64 * _expansions++];
					FixedUpdatePaused = new bool[FixedUpdateProcesses.Length];
					FixedUpdateHeld = new bool[FixedUpdateProcesses.Length];
					for (int l = 0; l < fixedUpdateProcesses.Length; l++)
					{
						FixedUpdateProcesses[l] = fixedUpdateProcesses[l];
						FixedUpdatePaused[l] = fixedUpdatePaused[l];
						FixedUpdateHeld[l] = fixedUpdateHeld[l];
					}
				}
				if (UpdateTimeValues(processIndex2.seg))
				{
					_lastFixedUpdateProcessSlot = _nextFixedUpdateProcessSlot;
				}
				processIndex2.i = _nextFixedUpdateProcessSlot++;
				FixedUpdateProcesses[processIndex2.i] = coroutine;
				if (tag != null)
				{
					AddTag(tag, handle);
				}
				_indexToHandle.Add(processIndex2, handle);
				_handleToIndex.Add(handle, processIndex2);
				while (prewarm)
				{
					if (!FixedUpdateProcesses[processIndex2.i].MoveNext())
					{
						if (_indexToHandle.ContainsKey(processIndex2))
						{
							KillCoroutinesOnInstance(_indexToHandle[processIndex2]);
						}
						prewarm = false;
					}
					else if (FixedUpdateProcesses[processIndex2.i] != null && float.IsNaN(FixedUpdateProcesses[processIndex2.i].Current))
					{
						if (ReplacementFunction != null)
						{
							FixedUpdateProcesses[processIndex2.i] = ReplacementFunction(FixedUpdateProcesses[processIndex2.i], _indexToHandle[processIndex2]);
							ReplacementFunction = null;
						}
						prewarm = !FixedUpdatePaused[processIndex2.i] && !FixedUpdateHeld[processIndex2.i];
					}
					else
					{
						prewarm = false;
					}
				}
				break;
			case Segment.LateUpdate:
				if (_nextLateUpdateProcessSlot >= LateUpdateProcesses.Length)
				{
					IEnumerator<float>[] lateUpdateProcesses = LateUpdateProcesses;
					bool[] lateUpdatePaused = LateUpdatePaused;
					bool[] lateUpdateHeld = LateUpdateHeld;
					LateUpdateProcesses = new IEnumerator<float>[LateUpdateProcesses.Length + 64 * _expansions++];
					LateUpdatePaused = new bool[LateUpdateProcesses.Length];
					LateUpdateHeld = new bool[LateUpdateProcesses.Length];
					for (int j = 0; j < lateUpdateProcesses.Length; j++)
					{
						LateUpdateProcesses[j] = lateUpdateProcesses[j];
						LateUpdatePaused[j] = lateUpdatePaused[j];
						LateUpdateHeld[j] = lateUpdateHeld[j];
					}
				}
				if (UpdateTimeValues(processIndex2.seg))
				{
					_lastLateUpdateProcessSlot = _nextLateUpdateProcessSlot;
				}
				processIndex2.i = _nextLateUpdateProcessSlot++;
				LateUpdateProcesses[processIndex2.i] = coroutine;
				if (tag != null)
				{
					AddTag(tag, handle);
				}
				_indexToHandle.Add(processIndex2, handle);
				_handleToIndex.Add(handle, processIndex2);
				while (prewarm)
				{
					if (!LateUpdateProcesses[processIndex2.i].MoveNext())
					{
						if (_indexToHandle.ContainsKey(processIndex2))
						{
							KillCoroutinesOnInstance(_indexToHandle[processIndex2]);
						}
						prewarm = false;
					}
					else if (LateUpdateProcesses[processIndex2.i] != null && float.IsNaN(LateUpdateProcesses[processIndex2.i].Current))
					{
						if (ReplacementFunction != null)
						{
							LateUpdateProcesses[processIndex2.i] = ReplacementFunction(LateUpdateProcesses[processIndex2.i], _indexToHandle[processIndex2]);
							ReplacementFunction = null;
						}
						prewarm = !LateUpdatePaused[processIndex2.i] && !LateUpdateHeld[processIndex2.i];
					}
					else
					{
						prewarm = false;
					}
				}
				break;
			case Segment.SlowUpdate:
				if (_nextSlowUpdateProcessSlot >= SlowUpdateProcesses.Length)
				{
					IEnumerator<float>[] slowUpdateProcesses = SlowUpdateProcesses;
					bool[] slowUpdatePaused = SlowUpdatePaused;
					bool[] slowUpdateHeld = SlowUpdateHeld;
					SlowUpdateProcesses = new IEnumerator<float>[SlowUpdateProcesses.Length + 64 * _expansions++];
					SlowUpdatePaused = new bool[SlowUpdateProcesses.Length];
					SlowUpdateHeld = new bool[SlowUpdateProcesses.Length];
					for (int i = 0; i < slowUpdateProcesses.Length; i++)
					{
						SlowUpdateProcesses[i] = slowUpdateProcesses[i];
						SlowUpdatePaused[i] = slowUpdatePaused[i];
						SlowUpdateHeld[i] = slowUpdateHeld[i];
					}
				}
				if (UpdateTimeValues(processIndex2.seg))
				{
					_lastSlowUpdateProcessSlot = _nextSlowUpdateProcessSlot;
				}
				processIndex2.i = _nextSlowUpdateProcessSlot++;
				SlowUpdateProcesses[processIndex2.i] = coroutine;
				if (tag != null)
				{
					AddTag(tag, handle);
				}
				_indexToHandle.Add(processIndex2, handle);
				_handleToIndex.Add(handle, processIndex2);
				while (prewarm)
				{
					if (!SlowUpdateProcesses[processIndex2.i].MoveNext())
					{
						if (_indexToHandle.ContainsKey(processIndex2))
						{
							KillCoroutinesOnInstance(_indexToHandle[processIndex2]);
						}
						prewarm = false;
					}
					else if (SlowUpdateProcesses[processIndex2.i] != null && float.IsNaN(SlowUpdateProcesses[processIndex2.i].Current))
					{
						if (ReplacementFunction != null)
						{
							SlowUpdateProcesses[processIndex2.i] = ReplacementFunction(SlowUpdateProcesses[processIndex2.i], _indexToHandle[processIndex2]);
							ReplacementFunction = null;
						}
						prewarm = !SlowUpdatePaused[processIndex2.i] && !SlowUpdateHeld[processIndex2.i];
					}
					else
					{
						prewarm = false;
					}
				}
				break;
			default:
				handle = default(CoroutineHandle);
				break;
			}
			localTime = num;
			deltaTime = num2;
			currentCoroutine = coroutineHandle;
			return handle;
		}

		public static int KillCoroutines()
		{
			return (!((Object)(object)_instance == (Object)null)) ? _instance.KillCoroutinesOnInstance() : 0;
		}

		public int KillCoroutinesOnInstance()
		{
			int result = _nextUpdateProcessSlot + _nextLateUpdateProcessSlot + _nextFixedUpdateProcessSlot + _nextSlowUpdateProcessSlot;
			UpdateProcesses = new IEnumerator<float>[256];
			UpdatePaused = new bool[256];
			UpdateHeld = new bool[256];
			UpdateCoroutines = 0;
			_nextUpdateProcessSlot = 0;
			LateUpdateProcesses = new IEnumerator<float>[8];
			LateUpdatePaused = new bool[8];
			LateUpdateHeld = new bool[8];
			LateUpdateCoroutines = 0;
			_nextLateUpdateProcessSlot = 0;
			FixedUpdateProcesses = new IEnumerator<float>[64];
			FixedUpdatePaused = new bool[64];
			FixedUpdateHeld = new bool[64];
			FixedUpdateCoroutines = 0;
			_nextFixedUpdateProcessSlot = 0;
			SlowUpdateProcesses = new IEnumerator<float>[64];
			SlowUpdatePaused = new bool[64];
			SlowUpdateHeld = new bool[64];
			SlowUpdateCoroutines = 0;
			_nextSlowUpdateProcessSlot = 0;
			_processTags.Clear();
			_taggedProcesses.Clear();
			_handleToIndex.Clear();
			_indexToHandle.Clear();
			_waitingTriggers.Clear();
			_expansions = (ushort)(_expansions / 2 + 1);
			return result;
		}

		public static int KillCoroutines(CoroutineHandle handle)
		{
			return ((Object)(object)ActiveInstances[handle.Key] != (Object)null) ? GetInstance(handle.Key).KillCoroutinesOnInstance(handle) : 0;
		}

		public int KillCoroutinesOnInstance(CoroutineHandle handle)
		{
			bool flag = false;
			if (_handleToIndex.ContainsKey(handle))
			{
				if (_waitingTriggers.ContainsKey(handle))
				{
					CloseWaitingProcess(handle);
				}
				flag = CoindexExtract(_handleToIndex[handle]) != null;
				RemoveTag(handle);
			}
			return flag ? 1 : 0;
		}

		public static int KillCoroutines(string tag)
		{
			return (!((Object)(object)_instance == (Object)null)) ? _instance.KillCoroutinesOnInstance(tag) : 0;
		}

		public int KillCoroutinesOnInstance(string tag)
		{
			if (tag == null)
			{
				return 0;
			}
			int num = 0;
			while (_taggedProcesses.ContainsKey(tag))
			{
				HashSet<CoroutineHandle>.Enumerator enumerator = _taggedProcesses[tag].GetEnumerator();
				enumerator.MoveNext();
				if (Nullify(_handleToIndex[enumerator.Current]))
				{
					if (_waitingTriggers.ContainsKey(enumerator.Current))
					{
						CloseWaitingProcess(enumerator.Current);
					}
					num++;
				}
				RemoveTag(enumerator.Current);
				if (_handleToIndex.ContainsKey(enumerator.Current))
				{
					_indexToHandle.Remove(_handleToIndex[enumerator.Current]);
					_handleToIndex.Remove(enumerator.Current);
				}
			}
			return num;
		}

		public static int PauseCoroutines()
		{
			return (!((Object)(object)_instance == (Object)null)) ? _instance.PauseCoroutinesOnInstance() : 0;
		}

		public int PauseCoroutinesOnInstance()
		{
			int num = 0;
			for (int i = 0; i < _nextUpdateProcessSlot; i++)
			{
				if (!UpdatePaused[i] && UpdateProcesses[i] != null)
				{
					num++;
					UpdatePaused[i] = true;
					if (UpdateProcesses[i].Current > GetSegmentTime(Segment.Update))
					{
						UpdateProcesses[i] = _InjectDelay(UpdateProcesses[i], UpdateProcesses[i].Current - GetSegmentTime(Segment.Update));
					}
				}
			}
			for (int i = 0; i < _nextLateUpdateProcessSlot; i++)
			{
				if (!LateUpdatePaused[i] && LateUpdateProcesses[i] != null)
				{
					num++;
					LateUpdatePaused[i] = true;
					if (LateUpdateProcesses[i].Current > GetSegmentTime(Segment.LateUpdate))
					{
						LateUpdateProcesses[i] = _InjectDelay(LateUpdateProcesses[i], LateUpdateProcesses[i].Current - GetSegmentTime(Segment.LateUpdate));
					}
				}
			}
			for (int i = 0; i < _nextFixedUpdateProcessSlot; i++)
			{
				if (!FixedUpdatePaused[i] && FixedUpdateProcesses[i] != null)
				{
					num++;
					FixedUpdatePaused[i] = true;
					if (FixedUpdateProcesses[i].Current > GetSegmentTime(Segment.FixedUpdate))
					{
						FixedUpdateProcesses[i] = _InjectDelay(FixedUpdateProcesses[i], FixedUpdateProcesses[i].Current - GetSegmentTime(Segment.FixedUpdate));
					}
				}
			}
			for (int i = 0; i < _nextSlowUpdateProcessSlot; i++)
			{
				if (!SlowUpdatePaused[i] && SlowUpdateProcesses[i] != null)
				{
					num++;
					SlowUpdatePaused[i] = true;
					if (SlowUpdateProcesses[i].Current > GetSegmentTime(Segment.SlowUpdate))
					{
						SlowUpdateProcesses[i] = _InjectDelay(SlowUpdateProcesses[i], SlowUpdateProcesses[i].Current - GetSegmentTime(Segment.SlowUpdate));
					}
				}
			}
			return num;
		}

		public static int PauseCoroutines(CoroutineHandle handle)
		{
			return ((Object)(object)ActiveInstances[handle.Key] != (Object)null) ? GetInstance(handle.Key).PauseCoroutinesOnInstance(handle) : 0;
		}

		public int PauseCoroutinesOnInstance(CoroutineHandle handle)
		{
			return (_handleToIndex.ContainsKey(handle) && !CoindexIsNull(_handleToIndex[handle]) && !SetPause(_handleToIndex[handle], newPausedState: true)) ? 1 : 0;
		}

		public static int PauseCoroutines(string tag)
		{
			return (!((Object)(object)_instance == (Object)null)) ? _instance.PauseCoroutinesOnInstance(tag) : 0;
		}

		public int PauseCoroutinesOnInstance(string tag)
		{
			if (tag == null || !_taggedProcesses.ContainsKey(tag))
			{
				return 0;
			}
			int num = 0;
			HashSet<CoroutineHandle>.Enumerator enumerator = _taggedProcesses[tag].GetEnumerator();
			while (enumerator.MoveNext())
			{
				if (!CoindexIsNull(_handleToIndex[enumerator.Current]) && !SetPause(_handleToIndex[enumerator.Current], newPausedState: true))
				{
					num++;
				}
			}
			return num;
		}

		public static int ResumeCoroutines()
		{
			return (!((Object)(object)_instance == (Object)null)) ? _instance.ResumeCoroutinesOnInstance() : 0;
		}

		public int ResumeCoroutinesOnInstance()
		{
			int num = 0;
			ProcessIndex processIndex = default(ProcessIndex);
			processIndex.i = 0;
			processIndex.seg = Segment.Update;
			while (processIndex.i < _nextUpdateProcessSlot)
			{
				if (UpdatePaused[processIndex.i] && UpdateProcesses[processIndex.i] != null)
				{
					UpdatePaused[processIndex.i] = false;
					num++;
				}
				processIndex.i++;
			}
			processIndex.i = 0;
			processIndex.seg = Segment.LateUpdate;
			while (processIndex.i < _nextLateUpdateProcessSlot)
			{
				if (LateUpdatePaused[processIndex.i] && LateUpdateProcesses[processIndex.i] != null)
				{
					LateUpdatePaused[processIndex.i] = false;
					num++;
				}
				processIndex.i++;
			}
			processIndex.i = 0;
			processIndex.seg = Segment.FixedUpdate;
			while (processIndex.i < _nextFixedUpdateProcessSlot)
			{
				if (FixedUpdatePaused[processIndex.i] && FixedUpdateProcesses[processIndex.i] != null)
				{
					FixedUpdatePaused[processIndex.i] = false;
					num++;
				}
				processIndex.i++;
			}
			processIndex.i = 0;
			processIndex.seg = Segment.SlowUpdate;
			while (processIndex.i < _nextSlowUpdateProcessSlot)
			{
				if (SlowUpdatePaused[processIndex.i] && SlowUpdateProc