Decompiled source of MoonstormSharedUtils v2.2.2

plugins/MSU.Runtime.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using HG;
using HG.Reflection;
using IL.RoR2;
using JetBrains.Annotations;
using LoadingScreenFix;
using MSU;
using MSU.AddressReferencedAssets;
using MSU.Config;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using Newtonsoft.Json;
using On.RoR2;
using On.RoR2.Items;
using On.RoR2.UI;
using R2API;
using R2API.AddressReferencedAssets;
using R2API.Networking;
using R2API.Networking.Interfaces;
using R2API.ScriptableObjects;
using RiskOfOptions;
using RiskOfOptions.Components.Panel;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.Achievements;
using RoR2.ContentManagement;
using RoR2.EntitlementManagement;
using RoR2.ExpansionManagement;
using RoR2.Items;
using RoR2.Projectile;
using RoR2.Skills;
using RoR2.UI;
using RoR2BepInExPack.VanillaFixes;
using ShaderSwapper;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.Serialization;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: InternalsVisibleTo("MoonstormSharedUtils", AllInternalsVisible = true)]
[assembly: InternalsVisibleTo("MSU.Editor", AllInternalsVisible = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace EntityStates.GameplayEvents
{
	public class GameplayEventState : EntityState
	{
		public GameplayEvent gameplayEvent { get; private set; }

		public override void OnEnter()
		{
			((EntityState)this).OnEnter();
			gameplayEvent = ((EntityState)this).GetComponent<GameplayEvent>();
		}
	}
}
namespace MSU
{
	[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
	public class AsyncAssetLoadAttribute : SearchableAttribute
	{
		public MethodInfo targetMethodInfo => ((SearchableAttribute)this).target as MethodInfo;

		[Obsolete("Use \"CreateParallelCoroutineForMod\"")]
		public static ParallelMultiStartCoroutine CreateCoroutineForMod(BaseUnityPlugin plugin)
		{
			List<SearchableAttribute> instances = SearchableAttribute.GetInstances<AsyncAssetLoadAttribute>();
			if (instances == null)
			{
				return new ParallelMultiStartCoroutine();
			}
			return CreateMultiStartCoroutineForMod((from att in instances.Where(IsValid)
				where IsFromMod((AsyncAssetLoadAttribute)(object)att, plugin)
				select att).Cast<AsyncAssetLoadAttribute>().ToList());
		}

		public static ParallelCoroutine CreateParallelCoroutineForMod(BaseUnityPlugin plugin)
		{
			List<SearchableAttribute> instances = SearchableAttribute.GetInstances<AsyncAssetLoadAttribute>();
			if (instances == null)
			{
				return new ParallelCoroutine();
			}
			return CreateCoroutineForMod((from att in instances.Where(IsValid)
				where IsFromMod((AsyncAssetLoadAttribute)(object)att, plugin)
				select att).Cast<AsyncAssetLoadAttribute>().ToList());
		}

		[Obsolete]
		private static ParallelMultiStartCoroutine CreateMultiStartCoroutineForMod(List<AsyncAssetLoadAttribute> attributes)
		{
			ParallelMultiStartCoroutine parallelMultiStartCoroutine = new ParallelMultiStartCoroutine();
			foreach (AsyncAssetLoadAttribute attribute in attributes)
			{
				parallelMultiStartCoroutine.Add((Func<IEnumerator>)attribute.targetMethodInfo.CreateDelegate(typeof(Func<IEnumerator>)));
			}
			return parallelMultiStartCoroutine;
		}

		private static ParallelCoroutine CreateCoroutineForMod(List<AsyncAssetLoadAttribute> attributes)
		{
			ParallelCoroutine parallelCoroutine = new ParallelCoroutine();
			foreach (AsyncAssetLoadAttribute attribute in attributes)
			{
				parallelCoroutine.Add((IEnumerator)attribute.targetMethodInfo.Invoke(null, null));
			}
			return parallelCoroutine;
		}

		private static bool IsValid(SearchableAttribute _att)
		{
			if (!(_att is AsyncAssetLoadAttribute asyncAssetLoadAttribute))
			{
				return false;
			}
			MethodInfo methodInfo = asyncAssetLoadAttribute.targetMethodInfo;
			if (!methodInfo.IsStatic)
			{
				MSULog.Info($"{asyncAssetLoadAttribute} is not applied to a Static method", 86, "IsValid");
			}
			Type returnType = methodInfo.ReturnType;
			if (returnType == null || returnType == typeof(void))
			{
				return false;
			}
			returnType.IsSameOrSubclassOf(typeof(IEnumerator));
			if (methodInfo.GetGenericArguments().Length != 0)
			{
				return false;
			}
			return true;
		}

		private static bool IsFromMod(AsyncAssetLoadAttribute attribute, BaseUnityPlugin plugin)
		{
			return attribute.targetMethodInfo.DeclaringType.Assembly == ((object)plugin).GetType().Assembly;
		}

		public override string ToString()
		{
			return "AsyncAssetLoadAttribute(TargetMethod=" + targetMethodInfo.DeclaringType.FullName + "." + targetMethodInfo.Name + "())";
		}
	}
	public abstract class BaseBuffBehaviour : MonoBehaviour
	{
		[AttributeUsage(AttributeTargets.Method)]
		public class BuffDefAssociation : SearchableAttribute
		{
		}

		private int _buffCount;

		public int buffCount
		{
			get
			{
				return _buffCount;
			}
			internal set
			{
				if (_buffCount != value)
				{
					int num = _buffCount;
					_buffCount = value;
					if (num == 0 && _buffCount > 0)
					{
						((Behaviour)this).enabled = true;
						OnFirstStackGained();
					}
					if (num > 0 && _buffCount == 0)
					{
						((Behaviour)this).enabled = false;
						OnAllStacksLost();
					}
				}
			}
		}

		public BuffIndex buffIndex { get; internal set; }

		public CharacterBody characterBody { get; internal set; }

		public bool hasAnyStacks => _buffCount > 0;

		protected virtual void OnFirstStackGained()
		{
		}

		protected virtual void OnAllStacksLost()
		{
		}

		protected virtual void Awake()
		{
			characterBody = ((Component)this).GetComponent<CharacterBody>();
		}

		protected virtual void OnDestroy()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			MSUContentManagement.OnBuffBehaviourDestroyed(characterBody, buffIndex);
		}
	}
	public abstract class BaseItemMasterBehaviour : MonoBehaviour
	{
		private struct NetworkContextSet
		{
			public ItemTypePair[] itemTypePairs;

			public FixedSizeArrayPool<BaseItemMasterBehaviour> behaviorArraysPool;

			public void SetItemTypePairs(List<ItemTypePair> itemTypePairs)
			{
				this.itemTypePairs = itemTypePairs.ToArray();
				behaviorArraysPool = new FixedSizeArrayPool<BaseItemMasterBehaviour>(this.itemTypePairs.Length);
			}
		}

		[MeansImplicitUse]
		[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
		public class ItemDefAssociationAttribute : SearchableAttribute
		{
			public Type behaviorTypeOverride;

			public bool useOnServer = true;

			public bool useOnClient = true;
		}

		public int stack;

		private static NetworkContextSet _server;

		private static NetworkContextSet _client;

		private static NetworkContextSet _shared;

		private static CharacterMaster _earlyAssignmentMaster = null;

		private static Dictionary<UnityObjectWrapperKey<CharacterMaster>, BaseItemMasterBehaviour[]> _masterToItemBehaviors = new Dictionary<UnityObjectWrapperKey<CharacterMaster>, BaseItemMasterBehaviour[]>();

		public CharacterMaster master { get; private set; }

		protected virtual void Awake()
		{
			master = _earlyAssignmentMaster;
			_earlyAssignmentMaster = null;
		}

		[SystemInitializer(new Type[] { typeof(ItemCatalog) })]
		private static IEnumerator Init()
		{
			MSULog.Info("Initializing the BaseItemMasterBehaviour system...", 37, "Init");
			List<ItemTypePair> server = new List<ItemTypePair>();
			List<ItemTypePair> client = new List<ItemTypePair>();
			List<ItemTypePair> shared = new List<ItemTypePair>();
			List<ItemDefAssociationAttribute> list = new List<ItemDefAssociationAttribute>();
			SearchableAttribute.GetInstances<ItemDefAssociationAttribute>(list);
			Type masterBehaviourType = typeof(BaseItemMasterBehaviour);
			Type itemDefType = typeof(ItemDef);
			foreach (ItemDefAssociationAttribute itemDefAssociationAttribute in list)
			{
				yield return null;
				MethodInfo methodInfo;
				if ((methodInfo = ((SearchableAttribute)itemDefAssociationAttribute).target as MethodInfo) == null)
				{
					MSULog.Error("ItemDefAssociationAttribute cannot be applied to object of type '" + ((object)itemDefAssociationAttribute)?.GetType().FullName + "'", 52, "Init");
					continue;
				}
				if (!methodInfo.IsStatic)
				{
					MSULog.Error("ItemDefAssociationAttribute cannot be applied to method " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + ": Method is not static.", 56, "Init");
					continue;
				}
				Type type = itemDefAssociationAttribute.behaviorTypeOverride ?? methodInfo.DeclaringType;
				if (!masterBehaviourType.IsAssignableFrom(type))
				{
					MSULog.Error("ItemDefAssociationAttribute cannot be applied to method " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + ": " + methodInfo.DeclaringType.FullName + " does not derive from " + masterBehaviourType.FullName + ".", 70, "Init");
					continue;
				}
				if (type.IsAbstract)
				{
					MSULog.Error("ItemDefAssociationAttribute cannot be applied to method " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + ": " + methodInfo.DeclaringType.FullName + " is an abstract type.", 85, "Init");
					continue;
				}
				if (!itemDefType.IsAssignableFrom(methodInfo.ReturnType))
				{
					object[] array = new object[7]
					{
						"ItemDefAssociationAttribute",
						methodInfo.DeclaringType.FullName,
						methodInfo.Name,
						methodInfo.DeclaringType.FullName,
						methodInfo,
						null,
						null
					};
					int num = 5;
					Type returnType = methodInfo.ReturnType;
					array[num] = ((returnType != null) ? returnType.FullName : null) ?? "void";
					array[6] = itemDefType.FullName;
					MSULog.Error(string.Format("{0} cannot be applied to method {1}.{2}: {3}.{4} returns type '{5}' instead of {6}.", array), 109, "Init");
					continue;
				}
				if (methodInfo.GetGenericArguments().Length != 0)
				{
					MSULog.Error(string.Format("{0} cannot be applied to method {1}.{2}: {3}.{4} must take no arguments.", "ItemDefAssociationAttribute", methodInfo.DeclaringType.FullName, methodInfo.Name, methodInfo.DeclaringType.FullName, methodInfo), 113, "Init");
					continue;
				}
				ItemDef val = (ItemDef)methodInfo.Invoke(null, Array.Empty<object>());
				if (!Object.op_Implicit((Object)(object)val))
				{
					MSULog.Error(methodInfo.DeclaringType.FullName + "." + methodInfo.Name + " returned null.", 127, "Init");
					continue;
				}
				if ((int)val.itemIndex < 0)
				{
					MSULog.Error($"{methodInfo.DeclaringType.FullName}.{methodInfo.Name} returned an ItemDef that's not registered in the ItemCatalog. result={val}", 131, "Init");
					continue;
				}
				if (itemDefAssociationAttribute.useOnServer)
				{
					server.Add(new ItemTypePair
					{
						itemIndex = val.itemIndex,
						behaviorType = type
					});
				}
				if (itemDefAssociationAttribute.useOnClient)
				{
					client.Add(new ItemTypePair
					{
						itemIndex = val.itemIndex,
						behaviorType = type
					});
				}
				if (itemDefAssociationAttribute.useOnServer || itemDefAssociationAttribute.useOnClient)
				{
					shared.Add(new ItemTypePair
					{
						itemIndex = val.itemIndex,
						behaviorType = type
					});
				}
			}
			_server.SetItemTypePairs(server);
			_client.SetItemTypePairs(client);
			_shared.SetItemTypePairs(shared);
			if (server.Count != 0 || client.Count != 0 || shared.Count != 0)
			{
				CharacterMaster.Awake += new hook_Awake(CharacterMaster_Awake);
				CharacterMaster.OnDestroy += new hook_OnDestroy(CharacterMaster_OnDestroy);
				CharacterMaster.OnInventoryChanged += new hook_OnInventoryChanged(CharacterMaster_OnInventoryChanged);
			}
		}

		private static void CharacterMaster_Awake(orig_Awake orig, CharacterMaster self)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			BaseItemMasterBehaviour[] value = GetNetworkContext().behaviorArraysPool.Request();
			_masterToItemBehaviors.Add(UnityObjectWrapperKey<CharacterMaster>.op_Implicit(self), value);
			orig.Invoke(self);
		}

		private static void CharacterMaster_OnDestroy(orig_OnDestroy orig, CharacterMaster self)
		{
			//IL_000d: 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)
			orig.Invoke(self);
			BaseItemMasterBehaviour[] array = _masterToItemBehaviors[UnityObjectWrapperKey<CharacterMaster>.op_Implicit(self)];
			for (int i = 0; i < array.Length; i++)
			{
				Object.Destroy((Object)(object)array[i]);
			}
			_masterToItemBehaviors.Remove(UnityObjectWrapperKey<CharacterMaster>.op_Implicit(self));
			if (NetworkServer.active || NetworkClient.active)
			{
				GetNetworkContext().behaviorArraysPool.Return(array, (ClearType<BaseItemMasterBehaviour>)0);
			}
		}

		private static void CharacterMaster_OnInventoryChanged(orig_OnInventoryChanged orig, CharacterMaster self)
		{
			orig.Invoke(self);
			UpdateMasterItemBehaviorStacks(self);
		}

		private static ref NetworkContextSet GetNetworkContext()
		{
			bool active = NetworkServer.active;
			bool active2 = NetworkClient.active;
			if (active)
			{
				if (active2)
				{
					return ref _shared;
				}
				return ref _server;
			}
			if (active2)
			{
				return ref _client;
			}
			throw new InvalidOperationException("Neither server nor client is running.");
		}

		private static void UpdateMasterItemBehaviorStacks(CharacterMaster master)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			ref NetworkContextSet networkContext = ref GetNetworkContext();
			if (!_masterToItemBehaviors.TryGetValue(UnityObjectWrapperKey<CharacterMaster>.op_Implicit(master), out var value))
			{
				return;
			}
			ItemTypePair[] itemTypePairs = networkContext.itemTypePairs;
			Inventory inventory = master.inventory;
			if (Object.op_Implicit((Object)(object)inventory))
			{
				for (int i = 0; i < itemTypePairs.Length; i++)
				{
					ItemTypePair val = itemTypePairs[i];
					SetItemStack(master, ref value[i], val.behaviorType, inventory.GetItemCount(val.itemIndex));
				}
				return;
			}
			for (int j = 0; j < itemTypePairs.Length; j++)
			{
				ref BaseItemMasterBehaviour reference = ref value[j];
				if ((Object)(object)reference != (Object)null)
				{
					Object.Destroy((Object)(object)reference);
					reference = null;
				}
			}
		}

		private static void SetItemStack(CharacterMaster master, ref BaseItemMasterBehaviour behavior, Type behaviorType, int stack)
		{
			if ((Object)(object)behavior == (Object)null != stack <= 0)
			{
				if (stack <= 0)
				{
					behavior.stack = 0;
					Object.Destroy((Object)(object)behavior);
					behavior = null;
				}
				else
				{
					_earlyAssignmentMaster = master;
					behavior = (BaseItemMasterBehaviour)(object)((Component)master).gameObject.AddComponent(behaviorType);
					_earlyAssignmentMaster = null;
				}
			}
			if ((Object)(object)behavior != (Object)null)
			{
				behavior.stack = stack;
			}
		}
	}
	public sealed class GameplayEvent : NetworkBehaviour
	{
		[Tooltip("When set to true, this gameplay event will call \"StartEvent\" on it's Start method")]
		[SyncVar]
		public bool beginOnStart;

		[Header("Gameplay Event Metadata")]
		[SyncVar]
		[Tooltip("When the event does an announcement, the announcement duration of the text will be this value. This value can be overwritten by the GameplayEventManager's spawn method at runtime.")]
		[SerializeField]
		private float _announcementDuration = 6f;

		[SerializeField]
		[SyncVar]
		[Tooltip("Is this value is greater than 0, the event will automatically stop once it has existed for this duration.")]
		private float _eventDuration = -1f;

		[Tooltip("When the event starts, this Token is used to inform the players.")]
		[SerializeField]
		private string _eventStartToken;

		[Tooltip("When the event starts, this sound effect is played to inform the players.")]
		[SerializeField]
		private NetworkSoundEventDef _eventStartSfx;

		[Tooltip("When the event ends, this token is used to inform the players.")]
		[SerializeField]
		private string _eventEndToken;

		[Tooltip("When the event ends, this sound effect is played to inform the players.")]
		[SerializeField]
		private NetworkSoundEventDef _eventEndSfx;

		[Tooltip("This color is used for the messages displayed when the event starts and ends. An outline color is calculated automatically.")]
		[SerializeField]
		private Color _eventColor;

		[Space]
		[Header("Gameplay Event Hooks")]
		[Tooltip("Called when this specific event begins")]
		[SerializeField]
		private UnityGameplayEvent _onEventStart;

		[Tooltip("Called when this specific event ends")]
		[SerializeField]
		private UnityGameplayEvent _onEventEnd;

		[SyncVar(hook = "Client_OnIsPlayingChanged")]
		private bool _isPlaying;

		[SyncVar]
		private bool _doNotAnnounceStart;

		[SyncVar]
		private bool _doNotAnnounceEnd;

		private float _eventDurationStopwatch;

		public float announcementDuration
		{
			get
			{
				return _announcementDuration;
			}
			set
			{
				Network_announcementDuration = value;
			}
		}

		public float eventDuration
		{
			get
			{
				return _eventDuration;
			}
			set
			{
				Network_eventDuration = value;
			}
		}

		public string eventStartToken => _eventStartToken;

		public NetworkSoundEventDef eventStartSfx => _eventStartSfx;

		public string eventEndToken => _eventEndToken;

		public NetworkSoundEventDef eventEndSfx => _eventEndSfx;

		public Color eventColor => _eventColor;

		[field: NonSerialized]
		public GameplayEventIndex gameplayEventIndex { get; internal set; }

		public bool isPlaying
		{
			get
			{
				return _isPlaying;
			}
			private set
			{
				Network_isPlaying = value;
			}
		}

		public bool doNotAnnounceStart
		{
			get
			{
				return _doNotAnnounceStart;
			}
			set
			{
				Network_doNotAnnounceStart = value;
			}
		}

		public bool doNotAnnounceEnd
		{
			get
			{
				return _doNotAnnounceEnd;
			}
			set
			{
				Network_doNotAnnounceEnd = value;
			}
		}

		public EntityStateIndex? customTextStateIndex { get; set; }

		public GenericObjectIndex? customTMPFontAssetIndex { get; set; }

		public NullableRef<GameplayEventRequirement> gameplayEventRequirement { get; private set; }

		public bool NetworkbeginOnStart
		{
			get
			{
				return beginOnStart;
			}
			[param: In]
			set
			{
				((NetworkBehaviour)this).SetSyncVar<bool>(value, ref beginOnStart, 1u);
			}
		}

		public float Network_announcementDuration
		{
			get
			{
				return _announcementDuration;
			}
			[param: In]
			set
			{
				((NetworkBehaviour)this).SetSyncVar<float>(value, ref _announcementDuration, 2u);
			}
		}

		public float Network_eventDuration
		{
			get
			{
				return _eventDuration;
			}
			[param: In]
			set
			{
				((NetworkBehaviour)this).SetSyncVar<float>(value, ref _eventDuration, 4u);
			}
		}

		public bool Network_isPlaying
		{
			get
			{
				return _isPlaying;
			}
			[param: In]
			set
			{
				ref bool reference = ref _isPlaying;
				if (NetworkServer.localClientActive && !((NetworkBehaviour)this).syncVarHookGuard)
				{
					((NetworkBehaviour)this).syncVarHookGuard = true;
					Client_OnIsPlayingChanged(value);
					((NetworkBehaviour)this).syncVarHookGuard = false;
				}
				((NetworkBehaviour)this).SetSyncVar<bool>(value, ref reference, 8u);
			}
		}

		public bool Network_doNotAnnounceStart
		{
			get
			{
				return _doNotAnnounceStart;
			}
			[param: In]
			set
			{
				((NetworkBehaviour)this).SetSyncVar<bool>(value, ref _doNotAnnounceStart, 16u);
			}
		}

		public bool Network_doNotAnnounceEnd
		{
			get
			{
				return _doNotAnnounceEnd;
			}
			[param: In]
			set
			{
				((NetworkBehaviour)this).SetSyncVar<bool>(value, ref _doNotAnnounceEnd, 32u);
			}
		}

		public static event GameplayEventDelegate onEventStartServer;

		public static event GameplayEventDelegate onEventStartGlobal;

		public event GameplayEventDelegate onEventStart;

		public static event GameplayEventDelegate onEventEndServer;

		public static event GameplayEventDelegate onEventEndGlobal;

		public event GameplayEventDelegate onEventEnd;

		private void Awake()
		{
			InstanceTracker.Add<GameplayEvent>(this);
			gameplayEventRequirement = ((Component)this).GetComponent<GameplayEventRequirement>();
		}

		private void Start()
		{
			if (beginOnStart && !isPlaying && NetworkServer.active)
			{
				StartEvent();
			}
		}

		private void OnDestroy()
		{
			if (isPlaying && NetworkServer.active)
			{
				EndEvent();
			}
			InstanceTracker.Remove<GameplayEvent>(this);
		}

		[Server]
		public void StartEvent()
		{
			if (!NetworkServer.active)
			{
				Debug.LogWarning((object)"[Server] function 'System.Void MSU.GameplayEvent::StartEvent()' called on client");
			}
			else if (!isPlaying)
			{
				_eventDurationStopwatch = 0f;
				isPlaying = true;
				GameplayEvent.onEventStartServer?.Invoke(this);
				GameplayEvent.onEventStartGlobal?.Invoke(this);
				this.onEventStart?.Invoke(this);
				((UnityEvent<GameplayEvent>)_onEventStart)?.Invoke(this);
				AnnounceEvent();
			}
		}

		private void FixedUpdate()
		{
			if (NetworkServer.active && !(eventDuration < 0f) && isPlaying)
			{
				_eventDurationStopwatch += Time.fixedDeltaTime;
				if (_eventDurationStopwatch > eventDuration)
				{
					EndEvent();
				}
			}
		}

		[Server]
		public void EndEvent()
		{
			if (!NetworkServer.active)
			{
				Debug.LogWarning((object)"[Server] function 'System.Void MSU.GameplayEvent::EndEvent()' called on client");
			}
			else if (isPlaying)
			{
				_eventDurationStopwatch = 0f;
				isPlaying = false;
				GameplayEvent.onEventEndServer?.Invoke(this);
				GameplayEvent.onEventEndGlobal?.Invoke(this);
				this.onEventEnd?.Invoke(this);
				((UnityEvent<GameplayEvent>)_onEventEnd)?.Invoke(this);
				AnnounceEvent();
			}
		}

		private void AnnounceEvent()
		{
			//IL_0052: 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_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)
			if ((!isPlaying || !doNotAnnounceStart) && (isPlaying || !doNotAnnounceEnd) && Object.op_Implicit((Object)(object)GameplayEventTextController.instance))
			{
				GameplayEventTextController.EventTextRequest request = default(GameplayEventTextController.EventTextRequest);
				if (customTextStateIndex.HasValue)
				{
					request.customTextState = new SerializableEntityStateType(EntityStateCatalog.GetStateType(customTextStateIndex.Value));
				}
				if (customTMPFontAssetIndex.HasValue)
				{
					request.genericObjectIndexThatPointsToTMP_FontAsset = customTMPFontAssetIndex.Value;
				}
				request.textDuration = announcementDuration;
				request.eventToken = eventStartToken;
				request.eventColor = eventColor;
				GameplayEventTextController.instance.EnqueueNewTextRequest(request, sendOverNetwork: false);
			}
		}

		[Client]
		private void Client_OnIsPlayingChanged(bool newVal)
		{
			if (!NetworkClient.active)
			{
				Debug.LogWarning((object)"[Client] function 'System.Void MSU.GameplayEvent::Client_OnIsPlayingChanged(System.Boolean)' called on server");
				return;
			}
			if (newVal)
			{
				GameplayEvent.onEventStartGlobal?.Invoke(this);
				this.onEventStart?.Invoke(this);
				((UnityEvent<GameplayEvent>)_onEventStart).Invoke(this);
			}
			else
			{
				GameplayEvent.onEventEndGlobal?.Invoke(this);
				this.onEventEnd?.Invoke(this);
				((UnityEvent<GameplayEvent>)_onEventEnd)?.Invoke(this);
			}
			AnnounceEvent();
		}

		public override bool OnSerialize(NetworkWriter writer, bool initialState)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (!initialState)
			{
				return false;
			}
			writer.Write(customTextStateIndex.HasValue);
			if (customTextStateIndex.HasValue)
			{
				NetworkExtensions.Write(writer, customTextStateIndex.Value);
			}
			writer.Write(customTMPFontAssetIndex.HasValue);
			if (customTMPFontAssetIndex.HasValue)
			{
				writer.Write(customTMPFontAssetIndex.Value);
			}
			return true;
		}

		public override void OnDeserialize(NetworkReader reader, bool initialState)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (initialState)
			{
				if (reader.ReadBoolean())
				{
					customTextStateIndex = NetworkExtensions.ReadEntityStateIndex(reader);
				}
				if (reader.ReadBoolean())
				{
					customTMPFontAssetIndex = reader.ReadGenericObjectIndex();
				}
			}
		}

		private void UNetVersion()
		{
		}

		public override void PreStartClient()
		{
		}
	}
	[Serializable]
	public class UnityGameplayEvent : UnityEvent<GameplayEvent>
	{
	}
	public delegate void GameplayEventDelegate(GameplayEvent gameplayEvent);
	[RequireComponent(typeof(GameplayEvent))]
	public class GameplayEventRequirement : MonoBehaviour
	{
		[Tooltip("At least this amount of stages should be completed before this GameplayEvent can spawn")]
		public int minimumStageCompletions = -1;

		[Tooltip("At least someone in the player team needs to have this unlockable unlocked before this GameplayEvent can spawn")]
		public AddressReferencedUnlockableDef requiredUnlockable;

		[Tooltip("None of the players should have this unlockable unlocked before this GameplayEvent can spawn")]
		public AddressReferencedUnlockableDef forbiddenUnlockable;

		[Tooltip("These ExpansionDefs need to be enabled in the run for this GameplayEvent to spawn")]
		public List<AddressReferencedExpansionDef> requiredExpansions;

		[Tooltip("The teleporter's charge needs to be bellow this value for a GameplayEvent to spawn")]
		[Range(0f, 1f)]
		public float maximumTeleportCharge = 0.25f;

		public GameplayEvent gameplayEvent { get; private set; }

		protected virtual void Awake()
		{
			gameplayEvent = ((Component)this).GetComponent<GameplayEvent>();
		}

		public virtual bool IsAvailable()
		{
			if (!Object.op_Implicit((Object)(object)Run.instance))
			{
				return false;
			}
			if (CheckStageCompletions() && CheckUnlockables() && CheckExpansions())
			{
				return CheckTeleporterCharge();
			}
			return false;
		}

		protected bool CheckStageCompletions()
		{
			if (!Object.op_Implicit((Object)(object)Run.instance))
			{
				return false;
			}
			if (minimumStageCompletions == -1)
			{
				return true;
			}
			return Run.instance.stageClearCount > minimumStageCompletions;
		}

		protected bool CheckUnlockables()
		{
			bool num = !AddressReferencedUnlockableDef.op_Implicit(requiredUnlockable) || Run.instance.IsUnlockableUnlocked(AddressReferencedUnlockableDef.op_Implicit(requiredUnlockable));
			bool flag = AddressReferencedUnlockableDef.op_Implicit(forbiddenUnlockable) && Run.instance.DoesEveryoneHaveThisUnlockableUnlocked(AddressReferencedUnlockableDef.op_Implicit(forbiddenUnlockable));
			if (num)
			{
				return !flag;
			}
			return false;
		}

		protected bool CheckExpansions()
		{
			foreach (AddressReferencedExpansionDef requiredExpansion in requiredExpansions)
			{
				if (AddressReferencedExpansionDef.op_Implicit(requiredExpansion) && !Run.instance.IsExpansionEnabled(AddressReferencedExpansionDef.op_Implicit(requiredExpansion)))
				{
					return false;
				}
			}
			return true;
		}

		protected bool CheckTeleporterCharge()
		{
			if (!Object.op_Implicit((Object)(object)TeleporterInteraction.instance))
			{
				return true;
			}
			return TeleporterInteraction.instance.chargeFraction < maximumTeleportCharge;
		}
	}
	public sealed class GameplayEventTextController : MonoBehaviour
	{
		public struct EventTextRequest
		{
			public string eventToken;

			public Color eventColor;

			public float textDuration;

			public SerializableEntityStateType? customTextState;

			public GenericObjectIndex genericObjectIndexThatPointsToTMP_FontAsset;

			public string tokenValue => Language.GetString(eventToken);

			public Color GetBestOutlineColor()
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				float num = default(float);
				float num2 = default(float);
				float num3 = default(float);
				Color.RGBToHSV(eventColor, ref num, ref num2, ref num3);
				float num4 = ((num3 > 0.5f) ? (-0.5f) : 0.5f);
				float num5 = Mathf.Clamp01(num2 + num4);
				float num6 = Mathf.Clamp01(num3 + num4);
				return Color.HSVToRGB(num, num5, num6);
			}
		}

		public abstract class EventTextState : EntityState
		{
			public float duration;

			public GameplayEventTextController textController { get; private set; }

			public UIJuice uiJuice { get; private set; }

			public override void OnEnter()
			{
				((EntityState)this).OnEnter();
				textController = ((EntityState)this).GetComponent<GameplayEventTextController>();
				uiJuice = ((EntityState)this).GetComponent<UIJuice>();
			}

			protected virtual void NullRequest()
			{
				textController.NullCurrentRequest();
			}
		}

		public class FadeInState : EventTextState
		{
			public override void OnEnter()
			{
				base.OnEnter();
				base.uiJuice.destroyOnEndOfTransition = false;
				base.uiJuice.transitionDuration = duration;
				base.uiJuice.TransitionAlphaFadeIn();
				base.uiJuice.originalAlpha = MSUConfig._maxOpacityForEventMessage;
				base.uiJuice.transitionEndAlpha = 1f;
			}

			public override void Update()
			{
				((EntityState)this).Update();
				if (((EntityState)this).age > duration)
				{
					((EntityState)this).outer.SetNextState((EntityState)(object)new WaitState
					{
						duration = duration
					});
				}
			}
		}

		public class WaitState : EventTextState
		{
			public override void Update()
			{
				((EntityState)this).Update();
				if (((EntityState)this).age > duration)
				{
					((EntityState)this).outer.SetNextState((EntityState)(object)new FadeOutState
					{
						duration = duration
					});
				}
			}
		}

		public class FadeOutState : EventTextState
		{
			public override void OnEnter()
			{
				base.OnEnter();
				base.uiJuice.TransitionAlphaFadeOut();
			}

			public override void Update()
			{
				((EntityState)this).Update();
				if (((EntityState)this).age > duration)
				{
					base.textController.NullCurrentRequest();
					((EntityState)this).outer.SetNextStateToMain();
				}
			}
		}

		internal class SendEventTextRequestToClientsMessage : INetMessage, ISerializableObject
		{
			public EventTextRequest request;

			public void Deserialize(NetworkReader reader)
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				request = default(EventTextRequest);
				request.eventToken = reader.ReadString();
				request.eventColor = reader.ReadColor();
				request.textDuration = reader.ReadSingle();
				if (reader.ReadBoolean())
				{
					request.customTextState = new SerializableEntityStateType(EntityStateCatalog.GetStateType(NetworkExtensions.ReadEntityStateIndex(reader)));
				}
				request.genericObjectIndexThatPointsToTMP_FontAsset = reader.ReadGenericObjectIndex();
			}

			public void OnReceived()
			{
				instance.EnqueueNewTextRequest(request, sendOverNetwork: false);
			}

			public void Serialize(NetworkWriter writer)
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				writer.Write(request.eventToken);
				writer.Write(request.eventColor);
				writer.Write(request.textDuration);
				writer.Write(request.customTextState.HasValue);
				if (request.customTextState.HasValue)
				{
					SerializableEntityStateType value = request.customTextState.Value;
					NetworkExtensions.Write(writer, EntityStateCatalog.GetStateIndex(((SerializableEntityStateType)(ref value)).stateType));
				}
				writer.Write(request.genericObjectIndexThatPointsToTMP_FontAsset);
			}

			public SendEventTextRequestToClientsMessage(EventTextRequest request)
			{
				this.request = request;
			}

			public SendEventTextRequestToClientsMessage()
			{
			}
		}

		private static GameObject _prefab;

		private Queue<EventTextRequest> _textRequests = new Queue<EventTextRequest>();

		private TMP_FontAsset _bombadierFontAsset;

		public static GameplayEventTextController instance { get; private set; }

		public EntityStateMachine textStateMachine { get; private set; }

		public HGTextMeshProUGUI textMeshProUGUI { get; private set; }

		public HUD hudInstance { get; private set; }

		public EventTextRequest? currentTextRequest { get; private set; }

		public RectTransform rectTransform { get; private set; }

		[SystemInitializer(new Type[] { })]
		private static IEnumerator SystemInit()
		{
			MSULog.Info("Initializing the GameplayEventTextController...", 59, "SystemInit");
			AssetBundleRequest request = MSUMain.msuAssetBundle.LoadAssetAsync<GameObject>("GameplayEventText");
			while (!((AsyncOperation)request).isDone)
			{
				yield return null;
			}
			Object asset = request.asset;
			_prefab = (GameObject)(object)((asset is GameObject) ? asset : null);
			HUD.Awake += new hook_Awake(SpawnAndGetInstance);
			MSUConfig._eventMessageFontSize.onConfigChanged += SetTextSize;
			MSUConfig._familyEventUsesEventAnnouncementInsteadOfChatMessage.onConfigChanged += ShouldAnnounceFamilyEventsAsGameplayEvents;
			NetworkingAPI.RegisterMessageType<SendEventTextRequestToClientsMessage>();
		}

		private static void ShouldAnnounceFamilyEventsAsGameplayEvents(bool announceAsGameplayEvents)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (announceAsGameplayEvents)
			{
				ClassicStageInfo.BroadcastFamilySelection -= new hook_BroadcastFamilySelection(BroadcastFamilySelection);
				ClassicStageInfo.BroadcastFamilySelection += new hook_BroadcastFamilySelection(BroadcastFamilySelection);
			}
			else
			{
				ClassicStageInfo.BroadcastFamilySelection -= new hook_BroadcastFamilySelection(BroadcastFamilySelection);
			}
		}

		private static IEnumerator BroadcastFamilySelection(orig_BroadcastFamilySelection orig, ClassicStageInfo self, string familySelectionChatString)
		{
			if (!Object.op_Implicit((Object)(object)instance))
			{
				yield return orig.Invoke(self, familySelectionChatString);
				yield break;
			}
			yield return (object)new WaitForSeconds(6f);
			instance.EnqueueNewTextRequest(new EventTextRequest
			{
				eventColor = Color.white,
				eventToken = familySelectionChatString,
				textDuration = 6f
			}, sendOverNetwork: true);
		}

		private static void SetTextSize(float newVal)
		{
			if (Object.op_Implicit((Object)(object)instance))
			{
				((TMP_Text)instance.textMeshProUGUI).fontSize = newVal;
				((TMP_Text)instance.textMeshProUGUI).fontSizeMax = newVal;
			}
		}

		private static void SpawnAndGetInstance(orig_Awake orig, HUD self)
		{
			orig.Invoke(self);
			Object.Instantiate<GameObject>(_prefab, self.mainContainer.transform);
			instance.hudInstance = self;
		}

		[ConCommand(/*Could not decode attribute arguments.*/)]
		private static void CC_TestEventText(ConCommandArgs args)
		{
			//IL_0028: 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)
			if (Object.op_Implicit((Object)(object)instance))
			{
				instance.EnqueueNewTextRequest(new EventTextRequest
				{
					eventToken = "Event Text Test",
					eventColor = Color.cyan,
					textDuration = 15f
				}, sendOverNetwork: true);
			}
		}

		public void EnqueueNewTextRequest(EventTextRequest request, bool sendOverNetwork)
		{
			if (sendOverNetwork)
			{
				SendRequestOverNetwork(request);
			}
			else
			{
				_textRequests.Enqueue(request);
			}
		}

		private void SendRequestOverNetwork(EventTextRequest request)
		{
			NetMessageExtensions.Send((INetMessage)(object)new SendEventTextRequestToClientsMessage(request), (NetworkDestination)3);
		}

		private void Update()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (!currentTextRequest.HasValue && _textRequests.Count > 0)
			{
				DequeueAndInitializeRequest();
			}
			else if (currentTextRequest.HasValue && textStateMachine.state is Idle)
			{
				EventTextRequest value = currentTextRequest.Value;
				bool hasValue = value.customTextState.HasValue;
				EventTextState eventTextState = null;
				if (hasValue)
				{
					SerializableEntityStateType value2 = value.customTextState.Value;
					eventTextState = (EventTextState)(object)EntityStateCatalog.InstantiateState(ref value2);
				}
				else
				{
					eventTextState = new FadeInState();
				}
				eventTextState.duration = (hasValue ? value.textDuration : (value.textDuration / 3f));
				textStateMachine.SetNextState((EntityState)(object)eventTextState);
			}
		}

		internal void NullCurrentRequest()
		{
			currentTextRequest = null;
		}

		private void DequeueAndInitializeRequest()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			currentTextRequest = _textRequests.Dequeue();
			string tokenValue = currentTextRequest.Value.tokenValue;
			Color eventColor = currentTextRequest.Value.eventColor;
			Color bestOutlineColor = currentTextRequest.Value.GetBestOutlineColor();
			GenericObjectIndex genericObjectIndexThatPointsToTMP_FontAsset = currentTextRequest.Value.genericObjectIndexThatPointsToTMP_FontAsset;
			((TMP_Text)textMeshProUGUI).text = tokenValue;
			((Graphic)textMeshProUGUI).color = eventColor;
			((TMP_Text)textMeshProUGUI).outlineColor = Color32.op_Implicit(bestOutlineColor);
			((TMP_Text)textMeshProUGUI).font = ((genericObjectIndexThatPointsToTMP_FontAsset == GenericObjectIndex.None) ? HGTextMeshProUGUI.defaultLanguageFont : GenericUnityObjectCatalog.GetObject<TMP_FontAsset>(genericObjectIndexThatPointsToTMP_FontAsset));
			rectTransform.anchoredPosition = Vector2.op_Implicit(new Vector3((float)MSUConfig._eventMessageXOffset, (float)MSUConfig._eventMessageYOffset));
		}

		private void Start()
		{
			_bombadierFontAsset = ((TMP_Text)textMeshProUGUI).font;
		}

		private void Awake()
		{
			textStateMachine = ((Component)this).GetComponent<EntityStateMachine>();
			textMeshProUGUI = ((Component)this).GetComponent<HGTextMeshProUGUI>();
			rectTransform = ((Component)this).GetComponent<RectTransform>();
		}

		private void OnEnable()
		{
			instance = this;
			((TMP_Text)textMeshProUGUI).text = string.Empty;
		}

		private void OnDisable()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}
	}
	public class ItemTierPickupDisplayHelper : MonoBehaviour
	{
		private PickupDisplay _display;

		private GameObject _vfxInstance;

		private void Awake()
		{
			_display = ((Component)this).GetComponent<PickupDisplay>();
		}

		public void RebuildCustomModel()
		{
			//IL_0014: 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_0029: 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: Invalid comparison between Unknown and I4
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_display))
			{
				return;
			}
			PickupDef pickupDef = PickupCatalog.GetPickupDef(_display.pickupIndex);
			if (pickupDef == null)
			{
				return;
			}
			ItemTier itemTier = pickupDef.itemTier;
			if ((int)itemTier > 10)
			{
				ItemTierDef itemTierDef = ItemTierCatalog.GetItemTierDef(itemTier);
				if (Object.op_Implicit((Object)(object)itemTierDef) && ItemTierModule._itemTierToPickupFX.TryGetValue(itemTierDef, out var value) && Object.op_Implicit((Object)(object)value))
				{
					_vfxInstance = Object.Instantiate<GameObject>(value, ((Component)_display).transform);
					_vfxInstance.transform.position = Vector3.zero;
				}
			}
		}

		public void DestroyCustomModel()
		{
			if (Object.op_Implicit((Object)(object)_vfxInstance))
			{
				Object.Destroy((Object)(object)_vfxInstance);
			}
		}
	}
	public sealed class MSUContentBehaviour : MonoBehaviour
	{
		public CharacterBody body;

		public MSUEliteBehaviour eliteBehaviour;

		private IStatItemBehavior[] _statItemBehaviors = Array.Empty<IStatItemBehavior>();

		private IBodyStatArgModifier[] _bodyStatArgModifiers = Array.Empty<IBodyStatArgModifier>();

		public bool hasMaster { get; private set; }

		private void Start()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			hasMaster = Object.op_Implicit((Object)(object)body.master);
			body.onInventoryChanged += CheckEquipmentAndStartGetInterfaces;
			EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef((EquipmentIndex)((!Object.op_Implicit((Object)(object)body.inventory)) ? (-1) : ((int)body.inventory.GetEquipmentIndex())));
			if (Object.op_Implicit((Object)(object)equipmentDef) && EquipmentModule.allMoonstormEquipments.TryGetValue(equipmentDef, out var value))
			{
				value.OnEquipmentObtained(body);
				if (Object.op_Implicit((Object)(object)equipmentDef.passiveBuffDef) && equipmentDef.passiveBuffDef.isElite)
				{
					eliteBehaviour.AssignNewIndex(equipmentDef.passiveBuffDef.eliteDef.eliteIndex);
				}
			}
			StartGetInterfaces();
		}

		private void CheckEquipmentAndStartGetInterfaces()
		{
			//IL_001a: 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)
			StartGetInterfaces();
			if (!hasMaster)
			{
				return;
			}
			EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(body.inventory.GetEquipmentIndex());
			if (Object.op_Implicit((Object)(object)equipmentDef) && Object.op_Implicit((Object)(object)eliteBehaviour))
			{
				if (!Object.op_Implicit((Object)(object)equipmentDef.passiveBuffDef) || !equipmentDef.passiveBuffDef.isElite)
				{
					eliteBehaviour.AssignNewIndex((EliteIndex)(-1));
				}
				else
				{
					eliteBehaviour.AssignNewIndex(equipmentDef.passiveBuffDef.eliteDef.eliteIndex);
				}
			}
		}

		public void StartGetInterfaces()
		{
			((MonoBehaviour)this).StartCoroutine(GetInterfaces());
		}

		private IEnumerator GetInterfaces()
		{
			yield return null;
			_statItemBehaviors = ((Component)this).GetComponents<IStatItemBehavior>();
			_bodyStatArgModifiers = ((Component)this).GetComponents<IBodyStatArgModifier>();
			body.healthComponent.onIncomingDamageReceivers = ((Component)this).GetComponents<IOnIncomingDamageServerReceiver>();
			body.healthComponent.onTakeDamageReceivers = ((Component)this).GetComponents<IOnTakeDamageServerReceiver>();
		}

		internal void GetStatCoefficients(StatHookEventArgs args)
		{
			for (int i = 0; i < _bodyStatArgModifiers.Length; i++)
			{
				_bodyStatArgModifiers[i].ModifyStatArguments(args);
			}
		}

		internal void RecalculateStatsStart()
		{
			for (int i = 0; i < _statItemBehaviors.Length; i++)
			{
				_statItemBehaviors[i].RecalculateStatsStart();
			}
		}

		internal void RecalculateStatsEnd()
		{
			for (int i = 0; i < _statItemBehaviors.Length; i++)
			{
				_statItemBehaviors[i].RecalculateStatsEnd();
			}
		}

		private void OnDestroy()
		{
			Object.Destroy((Object)(object)eliteBehaviour);
		}
	}
	public sealed class MSUEliteBehaviour : MonoBehaviour
	{
		public CharacterBody body;

		public CharacterModel characterModel;

		private GameObject _effectInstance;

		private EliteIndex _assignedIndex = (EliteIndex)(-1);

		internal void AssignNewIndex(EliteIndex index)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0018: Invalid comparison between Unknown and I4
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (_assignedIndex == index)
			{
				return;
			}
			_assignedIndex = index;
			if ((int)_assignedIndex == -1)
			{
				if (Object.op_Implicit((Object)(object)_effectInstance))
				{
					Object.Destroy((Object)(object)_effectInstance);
				}
				return;
			}
			if (Object.op_Implicit((Object)(object)_effectInstance))
			{
				Object.Destroy((Object)(object)_effectInstance);
			}
			if (EquipmentModule.eliteIndexToEffectPrefab.TryGetValue(index, out var value))
			{
				_effectInstance = Object.Instantiate<GameObject>(value, Object.op_Implicit((Object)(object)characterModel) ? ((Component)characterModel).transform : (Object.op_Implicit((Object)(object)body) ? body.transform : ((Component)this).transform), false);
			}
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)_effectInstance))
			{
				Object.Destroy((Object)(object)_effectInstance);
			}
		}
	}
	public interface IArtifactContentPiece : IContentPiece<ArtifactDef>, IContentPiece
	{
		NullableRef<ArtifactCode> artifactCode { get; }

		void OnArtifactEnabled();

		void OnArtifactDisabled();
	}
	public interface ICharacterContentPiece : IGameObjectContentPiece<CharacterBody>, IContentPiece<GameObject>, IContentPiece
	{
		NullableRef<GameObject> masterPrefab { get; }
	}
	public interface IEliteContentPiece : IEquipmentContentPiece, IContentPiece<EquipmentDef>, IContentPiece
	{
		List<EliteDef> eliteDefs { get; }
	}
	public interface IEquipmentContentPiece : IContentPiece<EquipmentDef>, IContentPiece
	{
		NullableRef<List<GameObject>> itemDisplayPrefabs { get; }

		bool Execute(EquipmentSlot slot);

		void OnEquipmentObtained(CharacterBody body);

		void OnEquipmentLost(CharacterBody body);
	}
	public interface IInteractableContentPiece : IGameObjectContentPiece<IInteractable>, IContentPiece<GameObject>, IContentPiece
	{
		NullableRef<InteractableCardProvider> cardProvider { get; }
	}
	public interface IItemContentPiece : IContentPiece<ItemDef>, IContentPiece
	{
		NullableRef<List<GameObject>> itemDisplayPrefabs { get; }
	}
	public interface IItemTierContentPiece : IContentPiece<ItemTierDef>, IContentPiece
	{
		NullableRef<SerializableColorCatalogEntry> colorIndex { get; }

		NullableRef<SerializableColorCatalogEntry> darkColorIndex { get; }

		GameObject pickupDisplayVFX { get; }

		List<ItemIndex> itemsWithThisTier { get; set; }

		List<PickupIndex> availableTierDropList { get; set; }
	}
	public interface IMonsterContentPiece : ICharacterContentPiece, IGameObjectContentPiece<CharacterBody>, IContentPiece<GameObject>, IContentPiece
	{
		NullableRef<MonsterCardProvider> cardProvider { get; }

		NullableRef<DirectorCardHolderExtended> dissonanceCard { get; }
	}
	public interface ISceneContentPiece : IContentPiece<SceneDef>, IContentPiece
	{
		NullableRef<MusicTrackDef> mainTrack { get; }

		NullableRef<MusicTrackDef> bossTrack { get; }

		NullableRef<Texture2D> bazaarTextureBase { get; }

		float? weightRelativeToSiblings { get; }

		bool? preLoop { get; }

		bool? postLoop { get; }

		void OnServerStageComplete(Stage stage);

		void OnServerStageBegin(Stage stage);
	}
	public interface ISurvivorContentPiece : ICharacterContentPiece, IGameObjectContentPiece<CharacterBody>, IContentPiece<GameObject>, IContentPiece
	{
		SurvivorDef survivorDef { get; }
	}
	public interface IVanillaSurvivorContentPiece : IContentPiece
	{
		SurvivorDef survivorDef { get; }

		IEnumerator InitializeAsync();
	}
	public interface IVoidItemContentPiece : IItemContentPiece, IContentPiece<ItemDef>, IContentPiece
	{
		List<ItemDef> GetInfectableItems();
	}
	public interface IContentPackModifier
	{
		void ModifyContentPack(ContentPack contentPack);
	}
	public interface IContentPiece
	{
		IEnumerator LoadContentAsync();

		bool IsAvailable(ContentPack contentPack);

		void Initialize();
	}
	public interface IContentPiece<T> : IContentPiece where T : Object
	{
		T asset { get; }
	}
	public interface IContentPieceProvider
	{
		ContentPack contentPack { get; }

		IContentPiece[] GetContents();
	}
	public interface IContentPieceProvider<T> : IContentPieceProvider where T : Object
	{
		new IContentPiece<T>[] GetContents();
	}
	public interface IGameObjectContentPiece<T> : IContentPiece<GameObject>, IContentPiece
	{
		T component { get; }
	}
	public static class ContentUtil
	{
		private class ContentPieceProvider : IContentPieceProvider
		{
			private ContentPack _contentPack;

			private IContentPiece[] _contentPieces;

			public ContentPack contentPack => _contentPack;

			public IContentPiece[] GetContents()
			{
				return _contentPieces;
			}

			public ContentPieceProvider(IEnumerable<IContentPiece> contentPieces, ContentPack contentPack)
			{
				_contentPieces = contentPieces.ToArray();
				_contentPack = contentPack;
			}
		}

		private class GenericContentPieceProvider<T> : IContentPieceProvider<T>, IContentPieceProvider where T : Object
		{
			private ContentPack _contentPack;

			private IContentPiece<T>[] _contentPieces;

			public ContentPack contentPack => _contentPack;

			public IContentPiece<T>[] GetContents()
			{
				return _contentPieces;
			}

			IContentPiece[] IContentPieceProvider.GetContents()
			{
				return _contentPieces;
			}

			public GenericContentPieceProvider(IEnumerable<IContentPiece<T>> contentPieces, ContentPack contentPack)
			{
				_contentPieces = contentPieces.ToArray();
				_contentPack = contentPack;
			}
		}

		private static ExpansionDef _dummyExpansion = ScriptableObject.CreateInstance<ExpansionDef>();

		public static void DisableArtifact(ArtifactDef artifactDef)
		{
			artifactDef.requiredExpansion = _dummyExpansion;
		}

		public static void DisableSurvivor(SurvivorDef survivorDef)
		{
			survivorDef.hidden = true;
		}

		public static void DisableItem(ItemDef itemDef)
		{
			itemDef.requiredExpansion = _dummyExpansion;
		}

		public static void DisableEquipment(EquipmentDef equipmentDef)
		{
			equipmentDef.requiredExpansion = _dummyExpansion;
		}

		public static IContentPieceProvider CreateContentPieceProvider<TContentPieceType>(BaseUnityPlugin plugin, ContentPack contentPack) where TContentPieceType : IContentPiece
		{
			return new ContentPieceProvider(AnalyzeForContentPieces<TContentPieceType>(plugin).OfType<IContentPiece>(), contentPack);
		}

		public static IEnumerable<TContentPieceType> AnalyzeForContentPieces<TContentPieceType>(BaseUnityPlugin plugin) where TContentPieceType : IContentPiece
		{
			return from t in ReflectionCache.GetTypes(((object)plugin).GetType().Assembly).Where(PassesFilterForContentPieceInterface<TContentPieceType>)
				select (TContentPieceType)Activator.CreateInstance(t);
		}

		public static IContentPieceProvider<TUObjectType> CreateGenericContentPieceProvider<TUObjectType>(BaseUnityPlugin baseUnityPlugin, ContentPack contentPack) where TUObjectType : Object
		{
			return new GenericContentPieceProvider<TUObjectType>(AnalyzeForGenericContentPieces<TUObjectType>(baseUnityPlugin), contentPack);
		}

		public static IEnumerable<IContentPiece<TUObjectType>> AnalyzeForGenericContentPieces<TUObjectType>(BaseUnityPlugin baseUnityPlugin) where TUObjectType : Object
		{
			return from t in ReflectionCache.GetTypes(((object)baseUnityPlugin).GetType().Assembly).Where(PassesFilterForObjectType<TUObjectType>)
				select (IContentPiece<TUObjectType>)Activator.CreateInstance(t);
		}

		public static IContentPieceProvider<GameObject> CreateGameObjectGenericContentPieceProvider<TComponentType>(BaseUnityPlugin baseUnityPlugin, ContentPack contentPack)
		{
			return new GenericContentPieceProvider<GameObject>(AnalyzeForGameObjectGenericContentPieces<TComponentType>(baseUnityPlugin), contentPack);
		}

		public static IEnumerable<IContentPiece<GameObject>> AnalyzeForGameObjectGenericContentPieces<TComponentTYpe>(BaseUnityPlugin baseUnityPlugin)
		{
			return from t in ReflectionCache.GetTypes(((object)baseUnityPlugin).GetType().Assembly)
				where PassesFilterForObjectType<GameObject>(t) && t.GetInterfaces().Contains(typeof(IGameObjectContentPiece<TComponentTYpe>))
				select (IContentPiece<GameObject>)Activator.CreateInstance(t);
		}

		public static void AddSingle<T>(this NamedAssetCollection<T> collection, T content) where T : class
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			string text = collection.nameProvider(content);
			string text2 = $"{content.GetType().Name}_{collection.Count}";
			if (!collection.assetToName.ContainsKey(content))
			{
				if (Utility.IsNullOrWhiteSpace(text))
				{
					text = text2;
				}
				collection.nameToAsset.ContainsKey(text);
				_ = 1;
				_ = collection.assetInfos.Length;
				ref AssetInfo<T>[] assetInfos = ref collection.assetInfos;
				AssetInfo<T> val = new AssetInfo<T>
				{
					asset = content,
					assetName = text
				};
				ArrayUtils.ArrayAppend<AssetInfo<T>>(ref assetInfos, ref val);
				collection.nameToAsset[text] = content;
				collection.assetToName[content] = text;
				Array.Sort(collection.assetInfos);
			}
		}

		public static void PopulateTypeFields<TAsset>(Type typeToPopulate, NamedAssetCollection<TAsset> assets) where TAsset : Object
		{
			string[] array = new string[assets.Length];
			for (int i = 0; i < assets.Length; i++)
			{
				array[i] = ((Object)assets[i]).name;
			}
			int num = 0;
			FieldInfo[] fields = typeToPopulate.GetFields(BindingFlags.Static | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (fieldInfo.FieldType.IsSameOrSubclassOf(typeof(TAsset)))
				{
					string name = fieldInfo.Name;
					TAsset val = assets.Find(name);
					if ((Object)(object)val != (Object)null)
					{
						fieldInfo.SetValue(null, val);
					}
					else
					{
						num++;
					}
				}
			}
		}

		public static void AddContentFromAssetCollection(this ContentPack contentPack, AssetCollection assetCollection)
		{
			AddContentFromCollectionInternal(contentPack, assetCollection.assets);
		}

		public static void AddContentFromAssetCollection(this ContentPack contentPack, AssetCollection assetCollection, Func<Object, bool> predicate)
		{
			Object[] assetCollection2 = assetCollection.assets.Where(predicate).ToArray();
			AddContentFromCollectionInternal(contentPack, assetCollection2);
		}

		public static TAsset FindAsset<TAsset>(this AssetCollection collection, string assetName) where TAsset : Object
		{
			return (from asset in collection.assets.OfType<TAsset>()
				where string.Equals(((Object)asset).name, assetName, StringComparison.OrdinalIgnoreCase)
				select asset).FirstOrDefault();
		}

		public static TAsset[] FindAssets<TAsset>(this AssetCollection collection) where TAsset : Object
		{
			return collection.assets.OfType<TAsset>().ToArray();
		}

		private static void AddContentFromCollectionInternal(ContentPack contentPack, Object[] assetCollection)
		{
			foreach (Object val in assetCollection)
			{
				try
				{
					if (Object.op_Implicit(val))
					{
						HandleAssetAddition(val, contentPack);
					}
				}
				catch (Exception data)
				{
					MSULog.Error(data, 341, "AddContentFromCollectionInternal");
				}
			}
		}

		private static void HandleAssetAddition(Object asset, ContentPack contentPack)
		{
			GameObject val = (GameObject)(object)((asset is GameObject) ? asset : null);
			if (val == null)
			{
				SkillDef val2 = (SkillDef)(object)((asset is SkillDef) ? asset : null);
				if (val2 == null)
				{
					SkillFamily val3 = (SkillFamily)(object)((asset is SkillFamily) ? asset : null);
					if (val3 == null)
					{
						SceneDef val4 = (SceneDef)(object)((asset is SceneDef) ? asset : null);
						if (val4 == null)
						{
							ItemDef val5 = (ItemDef)(object)((asset is ItemDef) ? asset : null);
							if (val5 == null)
							{
								ItemTierDef val6 = (ItemTierDef)(object)((asset is ItemTierDef) ? asset : null);
								if (val6 == null)
								{
									ItemRelationshipProvider val7 = (ItemRelationshipProvider)(object)((asset is ItemRelationshipProvider) ? asset : null);
									if (val7 == null)
									{
										ItemRelationshipType val8 = (ItemRelationshipType)(object)((asset is ItemRelationshipType) ? asset : null);
										if (val8 == null)
										{
											EquipmentDef val9 = (EquipmentDef)(object)((asset is EquipmentDef) ? asset : null);
											if (val9 == null)
											{
												BuffDef val10 = (BuffDef)(object)((asset is BuffDef) ? asset : null);
												if (val10 == null)
												{
													EliteDef val11 = (EliteDef)(object)((asset is EliteDef) ? asset : null);
													if (val11 == null)
													{
														UnlockableDef val12 = (UnlockableDef)(object)((asset is UnlockableDef) ? asset : null);
														if (val12 == null)
														{
															SurvivorDef val13 = (SurvivorDef)(object)((asset is SurvivorDef) ? asset : null);
															if (val13 == null)
															{
																ArtifactDef val14 = (ArtifactDef)(object)((asset is ArtifactDef) ? asset : null);
																if (val14 == null)
																{
																	SurfaceDef val15 = (SurfaceDef)(object)((asset is SurfaceDef) ? asset : null);
																	if (val15 == null)
																	{
																		NetworkSoundEventDef val16 = (NetworkSoundEventDef)(object)((asset is NetworkSoundEventDef) ? asset : null);
																		if (val16 == null)
																		{
																			MusicTrackDef val17 = (MusicTrackDef)(object)((asset is MusicTrackDef) ? asset : null);
																			if (val17 == null)
																			{
																				GameEndingDef val18 = (GameEndingDef)(object)((asset is GameEndingDef) ? asset : null);
																				if (val18 == null)
																				{
																					EntityStateConfiguration val19 = (EntityStateConfiguration)(object)((asset is EntityStateConfiguration) ? asset : null);
																					if (val19 == null)
																					{
																						ExpansionDef val20 = (ExpansionDef)(object)((asset is ExpansionDef) ? asset : null);
																						if (val20 == null)
																						{
																							EntitlementDef val21 = (EntitlementDef)(object)((asset is EntitlementDef) ? asset : null);
																							if (val21 == null)
																							{
																								MiscPickupDef val22 = (MiscPickupDef)(object)((asset is MiscPickupDef) ? asset : null);
																								if (val22 == null)
																								{
																									if (asset is EntityStateTypeCollection collection)
																									{
																										AddEntityStateTypes(collection, contentPack);
																									}
																								}
																								else
																								{
																									contentPack.miscPickupDefs.AddSingle<MiscPickupDef>(val22);
																								}
																							}
																							else
																							{
																								contentPack.entitlementDefs.AddSingle<EntitlementDef>(val21);
																							}
																						}
																						else
																						{
																							contentPack.expansionDefs.AddSingle<ExpansionDef>(val20);
																						}
																					}
																					else
																					{
																						contentPack.entityStateConfigurations.AddSingle<EntityStateConfiguration>(val19);
																					}
																				}
																				else
																				{
																					contentPack.gameEndingDefs.AddSingle<GameEndingDef>(val18);
																				}
																			}
																			else
																			{
																				contentPack.musicTrackDefs.AddSingle<MusicTrackDef>(val17);
																			}
																		}
																		else
																		{
																			contentPack.networkSoundEventDefs.AddSingle<NetworkSoundEventDef>(val16);
																		}
																	}
																	else
																	{
																		contentPack.surfaceDefs.AddSingle<SurfaceDef>(val15);
																	}
																}
																else
																{
																	contentPack.artifactDefs.AddSingle<ArtifactDef>(val14);
																}
															}
															else
															{
																contentPack.survivorDefs.AddSingle<SurvivorDef>(val13);
															}
														}
														else
														{
															contentPack.unlockableDefs.AddSingle<UnlockableDef>(val12);
														}
													}
													else
													{
														contentPack.eliteDefs.AddSingle<EliteDef>(val11);
													}
												}
												else
												{
													contentPack.buffDefs.AddSingle<BuffDef>(val10);
												}
											}
											else
											{
												contentPack.equipmentDefs.AddSingle<EquipmentDef>(val9);
											}
										}
										else
										{
											contentPack.itemRelationshipTypes.AddSingle<ItemRelationshipType>(val8);
										}
									}
									else
									{
										contentPack.itemRelationshipProviders.AddSingle<ItemRelationshipProvider>(val7);
									}
								}
								else
								{
									contentPack.itemTierDefs.AddSingle<ItemTierDef>(val6);
								}
							}
							else
							{
								contentPack.itemDefs.AddSingle<ItemDef>(val5);
							}
						}
						else
						{
							contentPack.sceneDefs.AddSingle<SceneDef>(val4);
						}
					}
					else
					{
						contentPack.skillFamilies.AddSingle<SkillFamily>(val3);
					}
				}
				else
				{
					contentPack.skillDefs.AddSingle<SkillDef>(val2);
				}
			}
			else
			{
				HandleGameObjectAddition(val, contentPack);
			}
		}

		private static void HandleGameObjectAddition(GameObject go, ContentPack contentPack)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			NetworkIdentity component = go.GetComponent<NetworkIdentity>();
			bool flag = false;
			CharacterBody val = default(CharacterBody);
			if (go.TryGetComponent<CharacterBody>(ref val))
			{
				flag = true;
				contentPack.bodyPrefabs.AddSingle<GameObject>(go);
			}
			CharacterMaster val2 = default(CharacterMaster);
			if (go.TryGetComponent<CharacterMaster>(ref val2))
			{
				flag = true;
				contentPack.masterPrefabs.AddSingle<GameObject>(go);
			}
			ProjectileController val3 = default(ProjectileController);
			if (go.TryGetComponent<ProjectileController>(ref val3))
			{
				flag = true;
				contentPack.projectilePrefabs.AddSingle<GameObject>(go);
			}
			Run val4 = default(Run);
			if (go.TryGetComponent<Run>(ref val4))
			{
				flag = true;
				contentPack.gameModePrefabs.AddSingle<GameObject>(go);
			}
			EffectComponent val5 = default(EffectComponent);
			if (go.TryGetComponent<EffectComponent>(ref val5))
			{
				contentPack.effectDefs.AddSingle<EffectDef>(new EffectDef(go));
			}
			if (Object.op_Implicit((Object)(object)component) && !flag)
			{
				contentPack.networkedObjectPrefabs.AddSingle<GameObject>(go);
			}
		}

		private static void AddEntityStateTypes(EntityStateTypeCollection collection, ContentPack contentPack)
		{
			//IL_000d: 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)
			SerializableEntityStateType[] stateTypes = collection.stateTypes;
			for (int i = 0; i < stateTypes.Length; i++)
			{
				SerializableEntityStateType val = stateTypes[i];
				if (((SerializableEntityStateType)(ref val)).stateType != null)
				{
					contentPack.entityStateTypes.AddSingle(((SerializableEntityStateType)(ref val)).stateType);
				}
			}
		}

		private static bool PassesFilterForContentPieceInterface<TContentPieceInterface>(Type t) where TContentPieceInterface : IContentPiece
		{
			bool num = !t.IsAbstract;
			bool flag = t.GetInterfaces().Contains(typeof(TContentPieceInterface));
			return num && flag;
		}

		private static bool PassesFilterForObjectType<T>(Type t) where T : Object
		{
			bool num = !t.IsAbstract;
			bool flag = t.GetInterfaces().Contains(typeof(IContentPiece<T>));
			return num && flag;
		}
	}
	[Obsolete("Use ParallelCoroutine instead, calling all the enumerator methods at the same frame makes no difference in terms of code execution")]
	public class ParallelMultiStartCoroutine : IEnumerator
	{
		private struct Wrapper
		{
			public Delegate coroutineDelegate;

			public object[] args;

			public IEnumerator coroutine;
		}

		private List<Wrapper> _wrappers = new List<Wrapper>();

		private IEnumerator _internalCoroutine;

		public bool isDone
		{
			get
			{
				if (_internalCoroutine == null)
				{
					Start();
				}
				return _internalCoroutine.IsDone();
			}
		}

		object IEnumerator.Current => _internalCoroutine.Current;

		public void Start()
		{
			for (int i = 0; i < _wrappers.Count; i++)
			{
				Wrapper value = _wrappers[i];
				value.coroutine = (IEnumerator)(value.coroutineDelegate?.DynamicInvoke(value.args));
				_wrappers[i] = value;
			}
			_internalCoroutine = InternalCoroutine();
		}

		public void Add(Func<IEnumerator> func)
		{
			_wrappers.Add(new Wrapper
			{
				coroutineDelegate = func
			});
		}

		public void Add<T1>(Func<T1, IEnumerator> func, T1 arg)
		{
			_wrappers.Add(new Wrapper
			{
				coroutineDelegate = func,
				args = new object[1] { arg }
			});
		}

		public void Add<T1, T2>(Func<T1, T2, IEnumerator> func, T1 arg1, T2 arg2)
		{
			_wrappers.Add(new Wrapper
			{
				coroutineDelegate = func,
				args = new object[2] { arg1, arg2 }
			});
		}

		public void Add<T1, T2, T3>(Func<T1, T2, T3, IEnumerator> func, T1 arg1, T2 arg2, T3 arg3)
		{
			_wrappers.Add(new Wrapper
			{
				coroutineDelegate = func,
				args = new object[3] { arg1, arg2, arg3 }
			});
		}

		public void Add<T1, T2, T3, T4>(Func<T1, T2, T3, T4, IEnumerator> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
		{
			_wrappers.Add(new Wrapper
			{
				coroutineDelegate = func,
				args = new object[4] { arg1, arg2, arg3, arg4 }
			});
		}

		public void Add<T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5, IEnumerator> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
		{
			_wrappers.Add(new Wrapper
			{
				coroutineDelegate = func,
				args = new object[5] { arg1, arg2, arg3, arg4, arg5 }
			});
		}

		private IEnumerator InternalCoroutine()
		{
			yield return null;
			bool encounteredUnfinished = true;
			while (encounteredUnfinished)
			{
				encounteredUnfinished = false;
				for (int i = _wrappers.Count - 1; i >= 0; i--)
				{
					Wrapper wrapper = _wrappers[i];
					if (!wrapper.coroutine.IsDone())
					{
						encounteredUnfinished = true;
						yield return wrapper.coroutine.Current;
					}
					else
					{
						_wrappers.RemoveAt(i);
					}
				}
			}
		}

		bool IEnumerator.MoveNext()
		{
			if (_internalCoroutine == null)
			{
				Start();
			}
			return _internalCoroutine?.MoveNext() ?? false;
		}

		void IEnumerator.Reset()
		{
			if (_internalCoroutine == null)
			{
				Start();
			}
			_internalCoroutine?.MoveNext();
		}
	}
	public class ParallelCoroutine : IEnumerator
	{
		private readonly List<IEnumerator> _coroutinesList = new List<IEnumerator>();

		private IEnumerator _internalCoroutine;

		public bool isDone => this.IsDone();

		public object Current => _internalCoroutine.Current;

		public ParallelCoroutine()
		{
			_internalCoroutine = InternalCoroutine();
		}

		public void Add(IEnumerator coroutine)
		{
			_coroutinesList.Add(coroutine);
		}

		public bool MoveNext()
		{
			return _internalCoroutine.MoveNext();
		}

		public void Reset()
		{
			_internalCoroutine.Reset();
		}

		private IEnumerator InternalCoroutine()
		{
			yield return null;
			bool encounteredUnfinished = true;
			while (encounteredUnfinished)
			{
				encounteredUnfinished = false;
				int i = _coroutinesList.Count - 1;
				while (i >= 0)
				{
					IEnumerator enumerator = _coroutinesList[i];
					if (enumerator.MoveNext())
					{
						encounteredUnfinished = true;
						yield return enumerator.Current;
					}
					else
					{
						_coroutinesList.RemoveAt(i);
					}
					int num = i - 1;
					i = num;
				}
			}
		}
	}
	public class DirectorCardHolderExtended : DirectorCardHolder
	{
		public ExpansionDef[] requiredExpansionDefs = Array.Empty<ExpansionDef>();

		public bool IsAvailable()
		{
			if (base.Card.IsAvailable())
			{
				return ExpansionRequirementMet();
			}
			return false;
		}

		public bool ExpansionRequirementMet()
		{
			ExpansionDef[] enabledExpansions = Run.instance.GetEnabledExpansions();
			ExpansionDef[] array = requiredExpansionDefs;
			foreach (ExpansionDef value in array)
			{
				if (!enabledExpansions.Contains(value))
				{
					return false;
				}
			}
			return true;
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct CharacterBodyIndexEqualityComparer : IEqualityComparer<CharacterBody>
	{
		public bool Equals(CharacterBody x, CharacterBody y)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0027: 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)
			if (!Object.op_Implicit((Object)(object)x) || !Object.op_Implicit((Object)(object)y))
			{
				return false;
			}
			if ((int)x.bodyIndex == -1 || (int)y.bodyIndex == -1)
			{
				return false;
			}
			return x.bodyIndex == y.bodyIndex;
		}

		public int GetHashCode(CharacterBody obj)
		{
			return ((object)obj).GetHashCode();
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct IInteractableNetworkIdentityAssetIDComparer : IEqualityComparer<IInteractable>
	{
		public bool Equals(IInteractable x, IInteractable y)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//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)
			if (x == null || y == null)
			{
				return false;
			}
			MonoBehaviour val = (MonoBehaviour)(object)((x is MonoBehaviour) ? x : null);
			MonoBehaviour val2 = (MonoBehaviour)(object)((y is MonoBehaviour) ? y : null);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
			{
				return false;
			}
			NetworkIdentity component = ((Component)val).GetComponent<NetworkIdentity>();
			NetworkIdentity component2 = ((Component)val2).GetComponent<NetworkIdentity>();
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2))
			{
				return false;
			}
			NetworkHash128 assetId = component.assetId;
			return ((NetworkHash128)(ref assetId)).Equals(component2.assetId);
		}

		public int GetHashCode(IInteractable obj)
		{
			return ((object)obj)?.GetHashCode() ?? (-1);
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
	public class FormatTokenAttribute : SearchableAttribute
	{
		public enum OperationTypeEnum
		{
			DivideByN,
			MultiplyByN,
			AddN,
			SubtractN,
			ModuloN
		}

		private object _cachedFormattingValue;

		public string languageToken { get; private set; }

		public OperationTypeEnum? operationType { get; private set; }

		public float? operationData { get; private set; }

		public int formattingIndex { get; private set; }

		internal object GetFormattingValue()
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			object obj = null;
			if (((SearchableAttribute)this).target is FieldInfo fieldInfo)
			{
				obj = fieldInfo.GetValue(null);
			}
			else
			{
				if (!(((SearchableAttribute)this).target is PropertyInfo propertyInfo))
				{
					throw new InvalidOperationException("FormatTokenAttribute is only valid in Fields and Properties");
				}
				obj = propertyInfo.GetMethod?.Invoke(null, null);
			}
			Type type = obj.GetType();
			if (type.IsSubclassOf(typeof(ConfiguredVariable)))
			{
				obj = ((ConfigEntryBase)(type.GetProperty("configEntryBase", BindingFlags.Instance | BindingFlags.Public).GetMethod?.Invoke(obj, null))).BoxedValue;
			}
			if (obj == null)
			{
				return string.Empty;
			}
			if (IsNumber(obj))
			{
				if (operationType.HasValue && operationData.HasValue)
				{
					switch (operationType.Value)
					{
					case OperationTypeEnum.MultiplyByN:
						obj = MultiplyByN(CastToFloat(obj));
						break;
					case OperationTypeEnum.DivideByN:
						obj = DivideByN(CastToFloat(obj));
						break;
					case OperationTypeEnum.AddN:
						obj = AddN(CastToFloat(obj));
						break;
					case OperationTypeEnum.ModuloN:
						obj = ModuloN(CastToFloat(obj));
						break;
					case OperationTypeEnum.SubtractN:
						obj = SubtractN(CastToFloat(obj));
						break;
					}
				}
				_cachedFormattingValue = obj;
			}
			else
			{
				_cachedFormattingValue = obj;
			}
			return _cachedFormattingValue;
		}

		private float CastToFloat(object obj)
		{
			return Convert.ToSingle(obj, CultureInfo.InvariantCulture);
		}

		private object MultiplyByN(float number)
		{
			float value = operationData.Value;
			return number * value;
		}

		private object DivideByN(float number)
		{
			float value = operationData.Value;
			return number / value;
		}

		private object AddN(float number)
		{
			float value = operationData.Value;
			return number + value;
		}

		private object SubtractN(float number)
		{
			return number - operationData;
		}

		private object ModuloN(float number)
		{
			float value = operationData.Value;
			return number % value;
		}

		private bool IsNumber(object value)
		{
			if (!(value is sbyte) && !(value is byte) && !(value is short) && !(value is ushort) && !(value is int) && !(value is uint) && !(value is long) && !(value is ulong) && !(value is float) && !(value is double))
			{
				return value is decimal;
			}
			return true;
		}

		public FormatTokenAttribute(string token, int formattingIndex = 0)
		{
			languageToken = token;
			this.formattingIndex = formattingIndex;
		}

		public FormatTokenAttribute(string token, OperationTypeEnum opType, float opData, int formattingIndex = 0)
		{
			languageToken = token;
			operationType = opType;
			operationData = opData;
			this.formattingIndex = formattingIndex;
		}
	}
	internal static class FormatTokenManager
	{
		private static Dictionary<string, FormatTokenAttribute[]> _cachedFormattingArray;

		[SystemInitializer(new Type[] { typeof(ConfigSystem) })]
		private static IEnumerator Init()
		{
			MSULog.Info("Initializing FormatTokenManager", 21, "Init");
			IEnumerator subroutine = CreateFormattingArray();
			while (!subroutine.IsDone())
			{
				yield return null;
			}
			foreach (Language allLanguage in Language.GetAllLanguages())
			{
				AddTokensFromLanguageFileLoaderAndFormatThem(allLanguage);
			}
			Language.onCurrentLanguageChanged += Language_onCurrentLanguageChanged;
			ModOptionPanelController.OnModOptionsExit = (Action)Delegate.Combine(ModOptionPanelController.OnModOptionsExit, (Action)delegate
			{
				MSULog.Info("Reformatting Tokens.", 40, "Init");
				AddTokensFromLanguageFileLoaderAndFormatThem(Language.currentLanguage);
			});
		}

		private static void Language_onCurrentLanguageChanged()
		{
			MSULog.Info("Changed to language " + Language.currentLanguageName + ".", 48, "Language_onCurrentLanguageChanged");
			AddTokensFromLanguageFileLoaderAndFormatThem(Language.currentLanguage);
		}

		private static void AddTokensFromLanguageFileLoaderAndFormatThem(Language currentLanguage)
		{
			string name = currentLanguage.name;
			if (!LanguageFileLoader._languageNameToRawTokenData.TryGetValue(name, out var value))
			{
				return;
			}
			List<(string, string)> list = new List<(string, string)>();
			foreach (var (text3, text4) in value)
			{
				if (_cachedFormattingArray.TryGetValue(text3, out var _))
				{
					list.Add((text3, text4));
				}
				else
				{
					currentLanguage.stringsByToken[text3] = text4;
				}
			}
			if (list.Count > 0)
			{
				((MonoBehaviour)MSUMain.instance).StartCoroutine(FormatTokensWhenConfigsAreBound(currentLanguage, list));
			}
		}

		private static IEnumerator FormatTokensWhenConfigsAreBound(Language target, List<(string, string)> tokenValuePair)
		{
			while (!ConfigSystem.configsBound)
			{
				yield return null;
			}
			foreach (var (text, text2) in tokenValuePair)
			{
				try
				{
					target.SetStringByToken(text, FormatString(text, text2, _cachedFormattingArray[text]));
				}
				catch (Exception arg)
				{
					MSULog.Error($"Failed to format string value for token {text} in language {target.name}. unformatted string will be used.\n{arg}", 100, "FormatTokensWhenConfigsAreBound");
					target.SetStringByToken(text, text2);
				}
			}
		}

		private static IEnumerator CreateFormattingArray()
		{
			List<FormatTokenAttribute> propertyFormatTokens = new List<FormatTokenAttribute>();
			List<FormatTokenAttribute> fieldFormatTokens = new List<FormatTokenAttribute>();
			IEnumerator subroutine = GetFormatTokenLists(propertyFormatTokens, fieldFormatTokens);
			while (!subroutine.IsDone())
			{
				yield return null;
			}
			Dictionary<string, FormatTokenAttribute[]> formattingDictionaryFromFields = new Dictionary<string, FormatTokenAttribute[]>();
			Dictionary<string, FormatTokenAttribute[]> formattingDictionaryFromProperties = new Dictionary<string, FormatTokenAttribute[]>();
			ParallelCoroutine parallelSubroutine = new ParallelCoroutine();
			parallelSubroutine.Add(CreateFormattingDictionary(propertyFormatTokens, formattingDictionaryFromProperties));
			parallelSubroutine.Add(CreateFormattingDictionary(fieldFormatTokens, formattingDictionaryFromFields));
			while (!parallelSubroutine.IsDone())
			{
				yield return null;
			}
			_cachedFormattingArray = new Dictionary<string, FormatTokenAttribute[]>();
			string key;
			FormatTokenAttribute[] value;
			foreach (KeyValuePair<string, FormatTokenAttribute[]> item in formattingDictionaryFromFields)
			{
				item.Deconstruct(out key, out value);
				string token2 = key;
				FormatTokenAttribute[] formattingArray2 = value;
				yield return null;
				_cachedFormattingArray[token2] = Array.Empty<FormatTokenAttribute>();
				FormatTokenAttribute[] arrayFromCache2 = _cachedFormattingArray[token2];
				for (int j = 0; j < formattingArray2.Length; j++)
				{
					yield return null;
					if (arrayFromCache2.Length < j + 1)
					{
						Array.Resize(ref arrayFromCache2, j + 1);
					}
					if (arrayFromCache2[j] == null)
					{
						arrayFromCache2[j] = formattingArray2[j];
					}
				}
				_cachedFormattingArray[token2] = arrayFromCache2;
			}
			foreach (KeyValuePair<string, FormatTokenAttribute[]> item2 in formattingDictionaryFromProperties)
			{
				item2.Deconstruct(out key, out value);
				string token2 = key;
				FormatTokenAttribute[] formattingArray2 = value;
				yield return null;
				if (!_cachedFormattingArray.ContainsKey(token2))
				{
					_cachedFormattingArray[token2] = Array.Empty<FormatTokenAttribute>();
				}
				FormatTokenAttribute[] arrayFromCache2 = _cachedFormattingArray[token2];
				for (int j = 0; j < formattingArray2.Length; j++)
				{
					yield return null;
					if (arrayFromCache2.Length < j + 1)
					{
						Array.Resize(ref arrayFromCache2, j + 1);
					}
					if (arrayFromCache2[j] == null)
					{
						arrayFromCache2[j] = formattingArray2[j];
					}
				}
				_cachedFormattingArray[token2] = arrayFromCache2;
			}
		}

		private static IEnumerator GetFormatTokenLists(List<FormatTokenAttribute> propertyFormatTokens, List<FormatTokenAttribute> fieldFormatTokens)
		{
			List<SearchableAttribute> source = SearchableAttribute.GetInstances<FormatTokenAttribute>() ?? new List<SearchableAttribute>();
			foreach (FormatTokenAttribute formatToken in source.Cast<FormatTokenAttribute>())
			{
				yield return null;
				if (((SearchableAttribute)formatToken).target is FieldInfo)
				{
					fieldFormatTokens.Add(formatToken);
				}
				else
				{
					propertyFormatTokens.Add(formatToken);
				}
			}
		}

		private static IEnumerator CreateFormattingDictionary(List<FormatTokenAttribute> source, Dictionary<string, FormatTokenAttribute[]> dest)
		{
			if (source.Count == 0)
			{
				yield break;
			}
			foreach (FormatTokenAttribute formatToken in source)
			{
				yield return null;
				try
				{
					string languageToken = formatToken.languageToken;
					int formattingIndex = formatToken.formattingIndex;
					if (!dest.ContainsKey(languageToken))
					{
						dest[languageToken] = Array.Empty<FormatTokenAttribute>();
					}
					FormatTokenAttribute[] array = dest[languageToken];
					if (array.Length < formattingIndex + 1)
					{
						Array.Resize(ref array, formattingIndex + 1);
					}
					if (array[formattingIndex] == null)
					{
						array[formattingIndex] = formatToken;
					}
					dest[languageToken] = array;
				}
				catch (Exception data)
				{
					MSULog.Error(data, 225, "CreateFormattingDictionary");
				}
			}
		}

		private static string FormatString(string token, string value, FormatTokenAttribute[] formattingArray)
		{
			object[] args = formattingArray.Select((FormatTokenAttribute att) => att.GetFormattingValue()).ToArray();
			return string.Format(value, args);
		}
	}
	public enum GameplayEventIndex
	{
		None = -1
	}
	public static class GameplayEventCatalog
	{
		public delegate void AddGameplayEventContentProviderDelegate(IGameplayEventContentProvider provider);

		public delegate void CollectGameplayEventContentProvidersDelegate(AddGameplayEventContentProviderDelegate addGameplayEventContentProvider);

		public interface IGameplayEventContentProvider
		{
			IEnumerator LoadGameplayEventsAsync(List<GameObject> dest);
		}

		private static GameObject[] _registeredGameplayEventObjects = Array.Empty<GameObject>();

		private static GameplayEvent[] _registeredGameplayEventComponents = Array.Empty<GameplayEvent>();

		private static readonly Dictionary<string, GameplayEventIndex> _nameToEventIndex = new Dictionary<string, GameplayEventIndex>(StringComparer.OrdinalIgnoreCase);

		public static ResourceAvailability catalogAvailability = default(ResourceAvailability);

		private static bool _initialized = false;

		public static int registeredGameplayEventCount => _registeredGameplayEventObjects.Length;

		public static event CollectGameplayEventContentProvidersDelegate collectGameplayEventContentProviders;

		public static GameplayEventIndex FindEventIndex(string eventName)
		{
			ThrowIfNotInitialized();
			if (_nameToEventIndex.TryGetValue(eventName, out var value))
			{
				return value;
			}
			return GameplayEventIndex.None;
		}

		public static GameObject GetGameplayEventObject(GameplayEventIndex index)
		{
			ThrowIfNotInitialized();
			return ArrayUtils.GetSafe<GameObject>(_registeredGameplayEventObjects, (int)index);
		}

		public static GameplayEvent GetGameplayEvent(GameplayEventIndex index)
		{
			ThrowIfNotInitialized();
			return ArrayUtils.GetSafe<GameplayEvent>(_registeredGameplayEventComponents, (int)index);
		}

		[SystemInitializer(new Type[] { })]
		private static IEnumerator Init()
		{
			MSULog.Info("Initializing the GameplayEvent Catalog...", 95, "Init");
			List<IGameplayEventContentProvider> contentProviders = new List<IGameplayEventContentProvider>();
			GameplayEventCatalog.collectGameplayEventContentProviders?.Invoke(AddGameplayEventContentProvider);
			List<GameObject> loadedEvents2 = new List<GameObject>();
			ParallelCoroutine coroutine = new ParallelCoroutine();
			foreach (IGameplayEventContentProvider contentProvider2 in contentProviders)
			{
				yield return null;
				coroutine.Add(contentProvider2.LoadGameplayEventsAsync(loadedEvents2));
			}
			while (!coroutine.isDone)
			{
				yield return null;
			}
			_nameToEventIndex.Clear();
			loadedEvents2 = loadedEvents2.OrderBy((GameObject go) => ((Object)go).name).ToList();
			_registeredGameplayEventObjects = RegisterGameplayEvents(loadedEvents2).ToArray();
			_registeredGameplayEventComponents = _registeredGameplayEventObjects.Select((GameObject g) => g.GetComponent<GameplayEvent>()).ToArray();
			_initialized = true;
			((ResourceAvailability)(ref catalogAvailability)).MakeAvailable();
			void AddGameplayEventContentProvider(IGameplayEventContentProvider contentProvider)
			{
				contentProviders.Add(contentProvider);
			}
		}

		private static List<GameObject> RegisterGameplayEvents(List<GameObject> _gameplayEvents)
		{
			List<GameObject> list = new List<GameObject>();
			for (int i = 0; i < _gameplayEvents.Count; i++)
			{
				try
				{
					EnsureValidity(_gameplayEvents[i], list);
				}
				catch (Exception data)
				{
					MSULog.Error(data, 139, "RegisterGameplayEvents");
				}
			}
			for (int j = 0; j < list.Count; j++)
			{
				GameObject val = list[j];
				GameplayEvent component = val.GetComponent<GameplayEvent>();
				component.gameplayEventIndex = (GameplayEventIndex)j;
				_nameToEventIndex.Add(((Object)val).name, component.gameplayEventIndex);
			}
			return list;
		}

		private static void EnsureValidity(GameObject gameplayEvent, List<GameObject> validEvents)
		{
			GameplayEvent gameplayEvent2 = default(GameplayEvent);
			if (!gameplayEvent.TryGetComponent<GameplayEvent>(ref gameplayEvent2))
			{
				throw new NullReferenceException($"GameObject {gameplayEvent} does not contain a GameplayEvent component.");
			}
			validEvents.Add(gameplayEvent);
		}

		private static void ThrowIfNotInitialized()
		{
			if (!_initialized)
			{
				throw new InvalidOperationException("GameplayEventCatalog not Initialized. Use \"catalogAvailability\" to call a method when the GameplayEventCatalog is initialized.");
			}
		}
	}
	public static class GameplayEventManager
	{
		public readonly struct GameplayEventSpawnArgs
		{
			public readonly GameObject gameplayEventPrefab;

			public readonly bool skipEventRequirementChecks;

			public readonly bool ignoreDuplicateEvents;

			public readonly bool doNotAnnounceStart;

			public readonly bool doNotAnnounceEnd;

			public readonly bool? beginOnStartOverride;

			public readonly float? expirationTimerOverride;

			public readonly float? announcementDurationOverride;

			public readonly EntityStateIndex? customTextStateIndex;

			public readonly GenericObjectIndex? customTMPFontAssetIndex;
		}

		public static bool GameplayEventExists(GameplayEvent gameplayEvent)
		{
			return GameplayEventExists(Object.op_Implicit((Object)(object)gameplayEvent) ? gameplayEvent.gameplayEventIndex : GameplayEventIndex.None);
		}

		public static bool GameplayEventExists(GameplayEventIndex index)
		{
			if (index == GameplayEventIndex.None)
			{
				return false;
			}
			foreach (GameplayEvent instances in InstanceTracker.GetInstancesList<GameplayEvent>())
			{
				if (instances.gameplayEventIndex == index)
				{
					return true;
				}
			}
			return false;
		}

		public static bool GameplayEventIsPlaying(GameplayEvent gameplayEvent)
		{
			return GameplayEventIsPlaying(Object.op_Implicit((Object)(object)gameplayEvent) ? gameplayEvent.gameplayEventIndex : GameplayEventIndex.None);
		}

		public static bool GameplayEventIsPlaying(GameplayEventIndex index)
		{
			foreach (GameplayEvent instances in InstanceTracker.GetInstancesList<GameplayEvent>())
			{
				if (instances.gameplayEventIndex == index)
				{
					return instances.isPlaying;
				}
			}
			return false;
		}

		public static GameplayEvent GetGameplayEventInstance(GameplayEvent prefabComponent)
		{
			return GetGameplayEventInstance(Object.op_Implicit((Object)(object)prefabComponent) ? prefabComponent.gameplayEventIndex : GameplayEventIndex.None);
		}

		public static GameplayEvent GetGameplayEventInstance(GameplayEventIndex index)
		{
			if (!GameplayEventExists(index))
			{
				return null;
			}
			foreach (GameplayEvent instances in InstanceTracker.GetInstancesList<GameplayEvent>())
			{
				if (instances.gameplayEventIndex == index)
				{
					return instances;
				}
			}
			return null;
		}

		public static bool AnyGameplayEventIsPlaying()
		{
			List<GameplayEvent> instancesList = InstanceTracker.GetInstancesList<GameplayEvent>();
			if (instancesList.Count == 0)
			{
				return false;
			}
			foreach (GameplayEvent item in instancesList)
			{
				if (item.isPlaying)
				{
					return true;
				}
			}
			return false;
		}

		public static bool AnyGameplayEventExists()
		{
			return InstanceTracker.GetInstancesList<GameplayEvent>().Count > 0;
		}

		public static GameplayEvent SpawnGameplayEvent(GameplayEventSpawnArgs args)
		{
			if (!NetworkServer.active)
			{
				return null;
			}
			GameObject gameplayEventPrefab = args.gameplayEventPrefab;
			GameplayEvent gameplayEvent = default(GameplayEvent);
			if (gameplayEventPrefab.TryGetComponent<GameplayEvent>(ref gameplayEvent))
			{
				return null;
			}
			if (gameplayEvent.gameplayEventIndex == GameplayEventIndex.None)
			{
				return null;
			}
			GameplayEventRequirement gameplayEventRequirement = default(GameplayEventRequirement);
			if (!args.skipEventRequirementChecks && gameplayEventPrefab.TryGetComponent<GameplayEventRequirement>(ref gameplayEventRequirement) && !gameplayEventRequirement.IsAvailable())
			{
				return null;
			}
			if (!args.ignoreDuplicateEvents && GameplayEventExists(gameplayEvent.gameplayEventIndex))
			{
				return null;
			}
			GameplayEvent component = Object.Instantiate<GameObject>(gameplayEventPrefab).GetComponent<GameplayEvent>();
			if (args.beginOnStartOverride.HasValue)
			{
				component.NetworkbeginOnStart = args.beginOnStartOverride.Value;
			}
			if (args.expirationTimerOverride.HasValue)
			{
				component.eventDuration = args.expirationTimerOverride.Value;
			}
			if (args.announcementDurationOverride.HasValue)
			{
				component.announcementDuration = args.announcementDurationOverride.Value;
			}
			component.doNotAnnounceEnd = args.doNotAnnounceEnd;
			component.doNotAnnounceStart = args.doNotAnnounceStart;
			NetworkServer.Spawn(((Component)component).gameObject);
			return component;
		}
	}
	public static class GenericUnityObjectCatalog
	{
		public delegate void AddGenericObjectContentProviderDelegate(IGenericObjectContentProvider provider);

		public delegate void CollectGenericObjectContentProvidersDelegate(AddGenericObjectContentProviderDelegate addGameplayEventContentProvider);

		public interface IGenericObjectContentProvider
		{
			IEnumerator LoadGenericObjectsAsync(List<GenericObjectEntry> dest);
		}

		public struct GenericObjectEntry
		{
			public Object unityObject;

			private string _nameOverride;

			public string name
			{
				get
				{
					if (!Utility.IsNullOrWhiteSpace(_nameOverride))
					{
						return _nameOverride;
					}
					return unityObject.name;
				}
			}

			public GenericObjectEntry(Object unityObject, string nameOverride = null)
			{
				_nameOverride = nameOverride;
				this.unityObject = unityObject;
			}
		}

		private static Object[] _registeredObjects = Array.Empty<Object>();

		private static Dictionary<string, GenericObjectIndex> _nameToGenericObjectIndex = new Dictionary<string, GenericObjectIndex>();

		public static ResourceAvailability catalogAvailability = default(ResourceAvailability);

		private static bool _initialized;

		public static int registeredObjectsCount => _registeredObjects.Length;

		public static event CollectGenericObjectContentProvidersDelegate collectGenericObjectContentProviders;

		public static GenericObjectIndex FindGenericObjectIndex(string name)
		{
			ThrowIfNotInitialized();
			if (_nameToGenericObjectIndex.TryGetValue(name, out var value))
			{
				return value;
			}
			return GenericObjectIndex.None;
		}

		public static T GetObject<T>(GenericObjectIndex index) where T : Object
		{
			ThrowIfNotInitialized();
			Object safe = ArrayUtils.GetSafe<Object>(_registeredObjects, (int)index);
			if (Object.op_Implicit(safe))
			{
				return (T)(object)safe;
			}
			return default(T);
		}

		public static Object GetObject(GenericObjectIndex index)
		{
			ThrowIfNotInitialized();
			return ArrayUtils.GetSafe<Object>(_registeredObjects, (int)index);
		}

		[SystemInitializer(new Type[] { })]
		private static IEnumerator Init()
		{
			MSULog.Info("Initializing the GenericObject Catalog...", 86, "Init");
			List<IGenericObjectContentProvider> contentProviders = new List<IGenericObjectContentProvider>();
			GenericUnityObjectCatalog.collectGenericObjectContentProviders?.Invoke(AddGenericObjectContentProvider);
			List<GenericObjectEntry> loadedObjects2 = new List<GenericObjectEntry>();
			ParallelCoroutine coroutine = new ParallelCoroutine();
			foreach (IGenericObjectContentProvider contentProvider2 in contentProviders)
			{
				yield return null;
				coroutine.Add(contentProvider2.LoadGenericObjectsAsync(loadedObjects2));
			}
			while (!coroutine.isDone)
			{
				yield return null;
			}
			_nameToGenericObjectIndex.Clear();
			loadedObjects2 = loadedObjects2.OrderBy((GenericObjectEntry obj) => obj.name).ToList();
			_registeredObjects = RegisterObjects(loadedObjects2).ToArray();
			_initialized = true;
			((ResourceAvailability)(ref catalogAvailability)).MakeAvailable();
			void AddGenericObjectContentProvider(IGenericObjectContentProvider contentProvider)
			{
				contentProviders.Add(contentProvider);
			}
		}

		private static List<Object> RegisterObjects(List<GenericObjectEntry> entries)
		{
			List<GenericObjectEntry> list = new List<GenericObjectEntry>();
			for (int i = 0; i < entries.Count; i++)
			{
				try
				{
					EnsureValidity(entries[i], list);
				}
				catch (Exception data)
				{
					MSULog.Error(data, 130, "RegisterObjects");
				}
			}
			for (int j = 0; j < list.Count; j++)
			{
				GenericObjectEntry genericObjectEntry = list[j];
				_nameToGenericObjectIndex.Add(genericObjectEntry.name, (GenericObjectIndex)j);
			}
			return list.Select((GenericObjectEntry goe) => goe.unityObject).ToList();
		}

		private static void EnsureValidity(GenericObjectEntry entry, List<GenericObjectEntry> validEntries)
		{
			if (Utility.IsNullOrWhiteSpace(entry.name))
			{
				throw new NullReferenceException("Entry's name is null");
			}
			validEntries.Add(entry);
		}

		private static void ThrowIfNotInitialized()
		{
			if (!_initialized)
			{
				throw new InvalidOperationException("GenericObjectCatalog not Initialized. Use \"catalogAvailability\" to call a method when the GenericObjectCatalog is initialized.");
			}
		}
	}
	public enum GenericObjectIndex
	{
		None = -1
	}
	internal static class ItemDisplayCatalog
	{
		private static StringComparer _comparer = StringComparer.OrdinalIgnoreCase;

		private static Dictionary<string, ItemDisplayRuleSet> _idrsDictionary = new Dictionary<string, ItemDisplayRuleSet>(_comparer);

		private static Dictionary<string, GameObject> _displayDictionary = new Dictionary<string, GameObject>(_comparer);

		public static ResourceAvailability catalogAvailability;

		public static GameObject GetItemDisplay(string key)
		{
			if (!_displayDictionary.ContainsKey(key))
			{
				return null;
			}
			return _displayDictionary[key];
		}

		public static ItemDisplayRuleSet GetItemDisplayRuleSet(string key)
		{
			if (!_idrsDictionary.ContainsKey(key))
			{
				return null;
			}
			return _idrsDictionary[key];
		}

		[SystemInitializer(new Type[] { })]
		private static IEnumerator SystemInitializer()
		{
			yield return null;
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate
			{
				MSULog.Info("Initializing the ItemDisplayCatalog...", 49, "SystemInitializer");
				CreateIDRSDictionary();
				CreateDisplayDictionary();
				((ResourceAvailability)(ref catalogAvailability)).MakeAvailable();
				_idrsDictionary.Clear();
				_displayDictionary.Clear();
			});
		}

		private static void CreateIDRSDictionary()
		{
			GameObject[] bodyPrefabs = BodyCatalog.bodyPrefabs;
			foreach (GameObject val in bodyPrefabs)
			{
				CharacterModel componentInChildren = val.GetComponentInChildren<CharacterModel>();
				if (!Object.op_Implicit((Object)(object)componentInChildren))
				{
					continue;
				}
				ItemDisplayRuleSet itemDisplayRuleSet = componentInChildren.itemDisplayRuleSet;
				if (Object.op_Implicit((Object)(object)itemDisplayRuleSet))
				{
					string key = (Utility.IsNullOrWhiteSpace(((Object)itemDisplayRuleSet).name) ? ("idrs" + ((Object)val).name) : ((Object)itemDisplayRuleSet).name);
					if (!_idrsDictionary.ContainsKey(key))
					{
						_idrsDictionary.Add(key, itemDisplayRuleSet);
					}
				}
			}
		}

		private static void CreateDisplayDictionary()
		{
			foreach (ItemDisplayRuleSet value3 in _idrsDictionary.Values)
			{
				PopulateDisplaysFromIDRS(value3);
			}
			foreach (KeyValuePair<ItemDef, IItemContentPiece> moonstormItem in ItemModule.moonstormItems)
			{
				moonstormItem.Deconstruct(out var _, out var value);
				PopulateDisplaysFromItems(value);
			}
			foreach (KeyValuePair<EquipmentDef, IEquipmentContentPiece> allMoonstormEquipment in EquipmentModule.allMoonstormEquipments)
			{
				allMoonstormEquipment.Deconstruct(out var _, out var value2);
				PopulateDisplaysFromEquips(value2);
			}
		}

		private static void PopulateDisplaysFromIDRS(ItemDisplayRuleSet idrs)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0017: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			KeyAssetRuleGroup[] keyAssetRuleGroups = idrs.keyAssetRuleGroups;
			foreach (KeyAssetRuleGroup val in keyAssetRuleGroups)
			{
				DisplayRuleGroup displayRuleGroup = val.displayRuleGroup;
				if (((DisplayRuleGroup)(ref displayRuleGroup)).isEmpty)
				{
					continue;
				}
				ItemDisplayRule[] rules = val.displayRuleGroup.rules;
				for (int j = 0; j < rules.Length; j++)
				{
					GameObject followerPrefab = rules[j].followerPrefab;
					if (!Object.op_Implicit((Object)(object)followerPrefab))
					{
						continue;
					}
					string key = (Utility.IsNullOrWhiteSpace(((Object)followerPrefab).name) ? $"{val.keyAsset.name}Display_{j}" : ((Object)followerPrefab).name);
					if (!_displayDictionary.ContainsKey(key))
					{
						_displayDictionary.Add(key, followerPrefab);
					}
					else if (!((Object)(object)_displayDictionary[key] == (Object)(object)followerPrefab))
					{
						int num = j - 1;