Decompiled source of AmorLib v1.0.0

AmorLib.dll

Decompiled 3 days ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using AIGraph;
using AmorLib.API;
using AmorLib.Dependencies;
using AmorLib.Events;
using AmorLib.Utils;
using AmorLib.Utils.Extensions;
using AmorLib.Utils.JsonElementConverters;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CullingSystem;
using GTFO.API;
using GTFO.API.Extensions;
using GTFO.API.JSON;
using GTFO.API.Utilities;
using GameData;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using InjectLib.JsonNETInjection.Supports;
using LevelGeneration;
using Localization;
using MTFO.Ext.PartialData;
using MTFO.Ext.PartialData.JsonConverters;
using Microsoft.CodeAnalysis;
using SNetwork;
using SemanticVersioning;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("AmorLib")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c778814919586b54c5f7c6f82f2464f32659dfe7")]
[assembly: AssemblyProduct("AmorLib")]
[assembly: AssemblyTitle("AmorLib")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace AmorLib
{
	[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
	internal sealed class CallConstructorOnLoadAttribute : Attribute
	{
	}
	[BepInPlugin("Amor.AmorLib", "AmorLib", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class EntryPoint : BasePlugin
	{
		public override void Load()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			new Harmony("Amor.AmorLib").PatchAll();
			CallAllAutoConstructors();
			Logger.Info("AmorLib is done loading!");
		}

		private void CallAllAutoConstructors()
		{
			IEnumerable<Type> enumerable = from t in AccessTools.GetTypesFromAssembly(((object)this).GetType().Assembly)
				where t.IsDefined(typeof(CallConstructorOnLoadAttribute), inherit: false)
				select t;
			foreach (Type item in enumerable)
			{
				RuntimeHelpers.RunClassConstructor(item.TypeHandle);
			}
		}
	}
	internal static class Logger
	{
		private static readonly ManualLogSource MLS;

		static Logger()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			MLS = new ManualLogSource("AmorLib");
			Logger.Sources.Add((ILogSource)(object)MLS);
		}

		public static void Info(BepInExInfoLogInterpolatedStringHandler handler)
		{
			MLS.LogInfo(handler);
		}

		public static void Info(string str)
		{
			MLS.LogMessage((object)str);
		}

		public static void Debug(BepInExDebugLogInterpolatedStringHandler handler)
		{
			MLS.LogDebug(handler);
		}

		public static void Debug(string str)
		{
			MLS.LogDebug((object)str);
		}

		public static void Error(BepInExErrorLogInterpolatedStringHandler handler)
		{
			MLS.LogError(handler);
		}

		public static void Error(string str)
		{
			MLS.LogError((object)str);
		}

		public static void Warn(BepInExWarningLogInterpolatedStringHandler handler)
		{
			MLS.LogWarning(handler);
		}

		public static void Warn(string str)
		{
			MLS.LogWarning((object)str);
		}
	}
}
namespace AmorLib.Utils
{
	[CallConstructorOnLoad]
	public static class CourseNodeUtil
	{
		private class DimensionMap
		{
			private const float IndexSize = 4f;

			public List<AIG_CourseNode>?[,] BuildNodeMap;

			public AIG_CourseNode[,][] NodeMap;

			public (int x, int z) MinCellBound;

			public (int x, int z) MaxCellBound;

			public (int x, int z) MapSize;

			public DimensionMap()
			{
				BuildNodeMap = null;
				NodeMap = null;
				MapSize = (0, 0);
				MinCellBound = (int.MaxValue, int.MaxValue);
				MaxCellBound = (int.MinValue, int.MinValue);
			}

			internal void UpdateBounds(Vector3 position)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				int val = (int)(position.x / 4f);
				int val2 = (int)(position.z / 4f);
				MinCellBound = (Math.Min(val, MinCellBound.x), Math.Min(val2, MinCellBound.z));
				MaxCellBound = (Math.Max(val, MaxCellBound.x), Math.Max(val2, MaxCellBound.z));
			}

			internal void CreateNodeMap()
			{
				MapSize = (MaxCellBound.x - MinCellBound.x + 1, MaxCellBound.z - MinCellBound.z + 1);
				BuildNodeMap = new List<AIG_CourseNode>[MapSize.x, MapSize.z];
				NodeMap = new AIG_CourseNode[MapSize.x, MapSize.z][];
			}

			internal (int x, int z) GetMapPos(Vector3 position)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				return (Math.Clamp((int)(position.x / 4f) - MinCellBound.x, 0, MapSize.x - 1), Math.Clamp((int)(position.z / 4f) - MinCellBound.z, 0, MapSize.z - 1));
			}

			internal List<AIG_CourseNode> GetBuildNodeList(Vector3 position)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				(int x, int z) mapPos = GetMapPos(position);
				int item = mapPos.x;
				int item2 = mapPos.z;
				List<AIG_CourseNode> list = BuildNodeMap[item, item2];
				if (list == null)
				{
					list = (BuildNodeMap[item, item2] = new List<AIG_CourseNode>());
				}
				return list;
			}

			internal void FinishBuild()
			{
				for (int i = 0; i < MapSize.x; i++)
				{
					for (int j = 0; j < MapSize.z; j++)
					{
						NodeMap[i, j] = BuildNodeMap[i, j]?.ToArray();
					}
				}
				BuildNodeMap = null;
			}

			public AIG_CourseNode[] GetNodes(Vector3 position)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c0: Expected O, but got Unknown
				//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
				var (num, num2) = GetMapPos(position);
				if (NodeMap[num, num2] != null)
				{
					return NodeMap[num, num2];
				}
				float num3 = Math.Max(MapSize.x, MapSize.z);
				for (int i = 1; (float)i < num3; i++)
				{
					int num4 = Math.Max(num - i, 0);
					int num5 = Math.Min(num + i, MapSize.x - 1);
					int num6 = Math.Max(num2 - i, 0);
					int num7 = Math.Min(num2 + i, MapSize.z - 1);
					for (int j = num4; j <= num5; j++)
					{
						if (NodeMap[j, num6] != null)
						{
							return NodeMap[j, num6];
						}
						if (NodeMap[j, num7] != null)
						{
							return NodeMap[j, num7];
						}
					}
					for (int k = num6 + 1; k <= num7 - 1; k++)
					{
						if (NodeMap[num4, k] != null)
						{
							return NodeMap[num4, k];
						}
						if (NodeMap[num5, k] != null)
						{
							return NodeMap[num5, k];
						}
					}
				}
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(66, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unable to get any node for (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Vector3>(position);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")! How are you even playing the game?!");
				}
				Logger.Error(val);
				return null;
			}
		}

		private static readonly Dictionary<eDimensionIndex, DimensionMap> _maps;

		static CourseNodeUtil()
		{
			_maps = new Dictionary<eDimensionIndex, DimensionMap>();
			LevelAPI.OnAfterBuildBatch += OnAfterBuildBatch;
		}

		private static void OnAfterBuildBatch(BatchName batch)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_0062: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			if ((int)batch != 38)
			{
				return;
			}
			_maps.Clear();
			IEnumerable<IGrouping<eDimensionIndex, AIG_NodeCluster>> enumerable = from c in ListExtensions.ToManaged<AIG_NodeCluster>(AIG_NodeCluster.AllNodeClusters)
				group c by c.m_courseNode.m_dimension.DimensionIndex;
			foreach (IGrouping<eDimensionIndex, AIG_NodeCluster> item in enumerable)
			{
				eDimensionIndex key = item.Key;
				DimensionMap orAddNew = _maps.GetOrAddNew(key);
				foreach (AIG_NodeCluster item2 in item)
				{
					Enumerator<AIG_INode> enumerator3 = item2.m_nodes.GetEnumerator();
					while (enumerator3.MoveNext())
					{
						AIG_INode current3 = enumerator3.Current;
						orAddNew.UpdateBounds(current3.Position);
					}
				}
				orAddNew.CreateNodeMap();
				foreach (AIG_NodeCluster item3 in item)
				{
					AIG_CourseNode courseNode = item3.CourseNode;
					int id = courseNode.NodeID;
					Enumerator<AIG_INode> enumerator5 = item3.m_nodes.GetEnumerator();
					while (enumerator5.MoveNext())
					{
						AIG_INode current5 = enumerator5.Current;
						List<AIG_CourseNode> buildNodeList = orAddNew.GetBuildNodeList(current5.Position);
						if (!buildNodeList.Any((AIG_CourseNode n) => n.NodeID == id))
						{
							buildNodeList.Add(courseNode);
						}
					}
				}
				orAddNew.FinishBuild();
			}
			Logger.Warn("Built DimensionMaps");
		}

		private static bool TryGetClosestNodeInCluster(AIG_NodeCluster cluster, Vector3 position, out AIG_INode node)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			AIG_VoxelNodeVolume voxelNodeVolume = cluster.m_nodeVolume.m_voxelNodeVolume;
			if (voxelNodeVolume.TryGetCloseVoxelNode_Safe(position, position.y - 0.5f, position.y + 0.5f, ref node, false))
			{
				return true;
			}
			int num = default(int);
			int num2 = default(int);
			voxelNodeVolume.GetGridPosition(position, ref num, ref num2);
			num = Mathf.Clamp(num, 0, voxelNodeVolume.m_countX - 1);
			num2 = Mathf.Clamp(num2, 0, voxelNodeVolume.m_countZ - 1);
			float num3 = float.PositiveInfinity;
			AIG_VoxelNode val = null;
			AIG_VoxelNodePillar val2 = default(AIG_VoxelNodePillar);
			for (int i = -1; i < 2; i++)
			{
				for (int j = -1; j < 2; j++)
				{
					if (!voxelNodeVolume.TryGetPillar(num + i, num2 + j, ref val2))
					{
						continue;
					}
					Enumerator<AIG_VoxelNode> enumerator = val2.m_nodes.GetEnumerator();
					while (enumerator.MoveNext())
					{
						AIG_VoxelNode current = enumerator.Current;
						if (current.ClusterID != cluster.ID)
						{
							continue;
						}
						Vector3 val3 = current.Position - position;
						float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
						if (sqrMagnitude < num3)
						{
							val = current;
							num3 = sqrMagnitude;
							if (num3 < 0.55f)
							{
								node = ((Il2CppObjectBase)val).Cast<AIG_INode>();
								return true;
							}
						}
					}
				}
			}
			if (val != null)
			{
				node = ((Il2CppObjectBase)val).Cast<AIG_INode>();
				return true;
			}
			return false;
		}

		public static AIG_CourseNode ResolveCourseNode(AIG_CourseNode[] list, Vector3 position)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			if (list == null)
			{
				return null;
			}
			if (list.Length == 1)
			{
				return list[0];
			}
			(AIG_CourseNode, AIG_INode)[] array = new(AIG_CourseNode, AIG_INode)[list.Length];
			int num = 0;
			foreach (AIG_CourseNode val in list)
			{
				if (!TryGetClosestNodeInCluster(val.m_nodeCluster, position, out AIG_INode node))
				{
					node = val.m_nodeCluster.m_nodes[0];
				}
				array[num++] = (val, node);
			}
			bool flag = false;
			float num2 = float.PositiveInfinity;
			AIG_CourseNode result = null;
			(AIG_CourseNode, AIG_INode)[] array2 = array;
			for (int j = 0; j < array2.Length; j++)
			{
				var (val2, val3) = array2[j];
				if (val3 != null)
				{
					bool flag2 = val3.Position.y - 0.25f <= position.y;
					Vector3 val4 = position - val3.Position;
					float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude;
					if ((!flag && flag2) || (flag == flag2 && sqrMagnitude < num2))
					{
						flag = flag2;
						num2 = sqrMagnitude;
						result = val2;
					}
				}
			}
			return result;
		}

		public static AIG_CourseNode GetCourseNode(Vector3 position, eDimensionIndex dimensionIndex)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!_maps.TryGetValue(dimensionIndex, out DimensionMap value))
			{
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(39, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("No Position-To-Node map for dimension ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<eDimensionIndex>(dimensionIndex);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("!");
				}
				Logger.Error(val);
				return null;
			}
			return ResolveCourseNode(value.GetNodes(position), position);
		}

		public static AIG_CourseNode[] GetCourseNodes(Vector3 position, eDimensionIndex dimensionIndex)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!_maps.TryGetValue(dimensionIndex, out DimensionMap value))
			{
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(39, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("No Position-To-Node map for dimension ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<eDimensionIndex>(dimensionIndex);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("!");
				}
				Logger.Error(val);
				return null;
			}
			return value.GetNodes(position);
		}
	}
	public abstract class GlobalBase
	{
		private eDimensionIndex _dimIndex = (eDimensionIndex)0;

		private LG_LayerType _layerType = (LG_LayerType)0;

		private eLocalZoneIndex _localIndex = (eLocalZoneIndex)0;

		private GlobalZoneIndex _struct;

		private (int dim, int layer, int zone) _tuple;

		public Dimension? Dimension;

		public LG_Zone? Zone;

		private bool _isDirty = true;

		[JsonPropertyOrder(-10)]
		public eDimensionIndex DimensionIndex
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return _dimIndex;
			}
			set
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				_dimIndex = value;
				MarkDirty();
			}
		}

		[JsonPropertyOrder(-10)]
		public LG_LayerType Layer
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return _layerType;
			}
			set
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				_layerType = value;
				MarkDirty();
			}
		}

		[JsonPropertyOrder(-10)]
		public eLocalZoneIndex LocalIndex
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return _localIndex;
			}
			set
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				_localIndex = value;
				MarkDirty();
			}
		}

		[JsonIgnore]
		public GlobalZoneIndex GlobalZoneIndex
		{
			get
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				Refresh();
				return _struct;
			}
		}

		[JsonIgnore]
		public (int dimension, int layer, int zone) IntTuple
		{
			get
			{
				Refresh();
				return _tuple;
			}
		}

		protected GlobalBase()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Refresh();
			LevelAPI.OnAfterBuildBatch += OnAfterBuildBatch;
			LevelAPI.OnLevelCleanup += OnLevelCleanup;
		}

		private void OnAfterBuildBatch(BatchName batch)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if ((int)batch == 8)
			{
				Dimension val = default(Dimension);
				Dimension = (Dimension.GetDimension(_dimIndex, ref val) ? val : null);
				Zone = (_tuple.TryGetZone(out LG_Zone zone) ? zone : null);
			}
		}

		private void OnLevelCleanup()
		{
			Dimension = null;
			Zone = null;
		}

		private void MarkDirty()
		{
			_isDirty = true;
		}

		private void Refresh()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (_isDirty)
			{
				_struct = GlobalIndexUtil.ToStruct(DimensionIndex, Layer, LocalIndex);
				_tuple = GlobalIndexUtil.ToIntTuple(DimensionIndex, Layer, LocalIndex);
				_isDirty = false;
			}
		}

		public override string ToString()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			return $"({DimensionIndex}, {Layer}, {LocalIndex})";
		}
	}
	public static class GlobalIndexUtil
	{
		public static (int dimension, int layer, int zone) ToIntTuple(this LG_Zone zone)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			return ToIntTuple(zone.DimensionIndex, zone.Layer.m_type, zone.LocalIndex);
		}

		public static (int dimension, int layer, int zone) ToIntTuple(this GlobalZoneIndex globalIndex)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			return ToIntTuple(globalIndex.Dimension, globalIndex.Layer, globalIndex.Zone);
		}

		public static (int dimension, int layer, int zone) ToIntTuple(eDimensionIndex dimension, LG_LayerType layer, eLocalZoneIndex zone)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected I4, but got Unknown
			//IL_0009: Expected I4, but got Unknown
			//IL_0009: Expected I4, but got Unknown
			return ((int)dimension, (int)layer, (int)zone);
		}

		public static GlobalZoneIndex ToStruct(this LG_Zone zone)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			return ToStruct(zone.DimensionIndex, zone.Layer.m_type, zone.LocalIndex);
		}

		public static GlobalZoneIndex ToStruct(eDimensionIndex dimension, LG_LayerType layer, eLocalZoneIndex zone)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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)
			return new GlobalZoneIndex(dimension, layer, zone);
		}

		public static bool TryGetZone(this (int, int, int) index, [MaybeNullWhen(false)] out LG_Zone zone)
		{
			return TryGetZone((eDimensionIndex)index.Item1, (LG_LayerType)(byte)index.Item2, (eLocalZoneIndex)index.Item3, out zone);
		}

		public static bool TryGetZone(this GlobalZoneIndex index, [MaybeNullWhen(false)] out LG_Zone zone)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			return TryGetZone(index.Dimension, index.Layer, index.Zone, out zone);
		}

		public static bool TryGetZone(eDimensionIndex dimension, LG_LayerType layer, eLocalZoneIndex localIndex, out LG_Zone? zone)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!Builder.CurrentFloor.TryGetZoneByLocalIndex(dimension, layer, localIndex, ref zone))
			{
				Logger.Error("Unable to find zone in level!");
				return false;
			}
			return true;
		}
	}
	public static class JsonSerializerUtil
	{
		public static JsonSerializerOptions CreateDefaultSettings(bool useLocalizedText = true, bool usePartialData = false, bool useInjectLib = false)
		{
			JsonSerializerOptions jsonSerializerOptions = (useLocalizedText ? new JsonSerializerOptions(JsonSerializer.DefaultSerializerSettingsWithLocalizedText) : new JsonSerializerOptions(JsonSerializer.DefaultSerializerSettings));
			if (usePartialData && PData_Wrapper.IsLoaded)
			{
				jsonSerializerOptions.Converters.Add(PData_Wrapper.PersistentIDConverter);
			}
			if (useInjectLib && InjectLib_Wrapper.IsLoaded)
			{
				jsonSerializerOptions.Converters.Add(InjectLib_Wrapper.InjectLibConverter);
			}
			return jsonSerializerOptions;
		}
	}
}
namespace AmorLib.Utils.JsonElementConverters
{
	[JsonConverter(typeof(BoolBaseConverter))]
	public struct BoolBase
	{
		public BoolMode Mode;

		public static readonly BoolBase False = new BoolBase(BoolMode.False);

		public static readonly BoolBase True = new BoolBase(BoolMode.True);

		public static readonly BoolBase Unchanged = new BoolBase(BoolMode.Unchanged);

		public BoolBase(bool mode)
		{
			Mode = (mode ? BoolMode.True : BoolMode.False);
		}

		public BoolBase(BoolMode mode)
		{
			Mode = mode;
		}

		public readonly bool GetValue(bool originalValue)
		{
			return Mode switch
			{
				BoolMode.True => true, 
				BoolMode.False => false, 
				_ => originalValue, 
			};
		}
	}
	public enum BoolMode
	{
		False,
		True,
		Unchanged
	}
	public sealed class BoolBaseConverter : JsonConverter<BoolBase>
	{
		public override bool HandleNull => false;

		public override bool CanConvert(Type objectType)
		{
			return objectType == typeof(BoolBase);
		}

		public override BoolBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			switch (reader.TokenType)
			{
			case JsonTokenType.String:
			{
				string text = reader.GetString()?.Trim();
				if (string.IsNullOrEmpty(text))
				{
					throw new JsonException("BoolBase string value is null or empty!");
				}
				if (text.EqualsAny(true, "Unchanged", "Ignore", "Keep", "Original", "KeepOriginal"))
				{
					return BoolBase.Unchanged;
				}
				if (bool.TryParse(text, out var result))
				{
					return new BoolBase(result);
				}
				throw new JsonException("Cannot parse BoolBase string: " + text + "! Are you sure it's in right format?");
			}
			case JsonTokenType.True:
				return BoolBase.True;
			case JsonTokenType.False:
				return BoolBase.False;
			default:
				throw new JsonException($"BoolBaseJson type: {reader.TokenType} is not implemented!");
			}
		}

		public override void Write(Utf8JsonWriter writer, BoolBase value, JsonSerializerOptions options)
		{
			switch (value.Mode)
			{
			case BoolMode.True:
				writer.WriteBooleanValue(value: true);
				break;
			case BoolMode.False:
				writer.WriteBooleanValue(value: false);
				break;
			case BoolMode.Unchanged:
				writer.WriteStringValue("Unchanged");
				break;
			}
			writer.WriteCommentValue("BoolBase");
		}
	}
	[JsonConverter(typeof(LocaleTextConverter))]
	public struct LocaleText : IEquatable<LocaleText>
	{
		public uint ID;

		public string RawText;

		public static readonly LocaleText Empty = new LocaleText(string.Empty);

		private readonly string TextFallback => (ID == 0) ? RawText : Text.Get(ID);

		public LocaleText(LocalizedText baseText)
		{
			RawText = ((Object)baseText).ToString();
			ID = baseText.Id;
		}

		public LocaleText(string text)
		{
			if (PData_Wrapper.TryGetGUID(text, out var guid))
			{
				RawText = string.Empty;
				ID = guid;
			}
			else
			{
				RawText = text;
				ID = 0u;
			}
		}

		public LocaleText(uint id)
		{
			RawText = string.Empty;
			ID = id;
		}

		public readonly LocalizedText ToLocalizedText()
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			return new LocalizedText
			{
				Id = ID,
				UntranslatedText = TextFallback
			};
		}

		public static explicit operator LocaleText(LocalizedText localizedText)
		{
			return new LocaleText(localizedText);
		}

		public static explicit operator LocaleText(string text)
		{
			return new LocaleText(text);
		}

		public static implicit operator LocalizedText(LocaleText localeText)
		{
			return localeText.ToLocalizedText();
		}

		public static implicit operator string(LocaleText localeText)
		{
			return localeText.ToString();
		}

		public override readonly string ToString()
		{
			return TextFallback;
		}

		public readonly bool Equals(LocaleText other)
		{
			return ID == other.ID && string.Equals(RawText, other.RawText, StringComparison.Ordinal);
		}

		public override readonly bool Equals(object? obj)
		{
			return obj is LocaleText other && Equals(other);
		}

		public override readonly int GetHashCode()
		{
			return HashCode.Combine(ID, RawText);
		}

		public static bool operator ==(LocaleText left, LocaleText right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(LocaleText left, LocaleText right)
		{
			return !(left == right);
		}
	}
	public class LocaleTextConverter : JsonConverter<LocaleText>
	{
		public override bool HandleNull => true;

		public override LocaleText Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			return reader.TokenType switch
			{
				JsonTokenType.String => new LocaleText(reader.GetString()), 
				JsonTokenType.Number => new LocaleText(reader.GetUInt32()), 
				JsonTokenType.Null => LocaleText.Empty, 
				_ => throw new JsonException($"LocaleTextJson type: {reader.TokenType} is not implemented!"), 
			};
		}

		public override void Write(Utf8JsonWriter writer, LocaleText value, JsonSerializerOptions options)
		{
			if (value.ID != 0)
			{
				writer.WriteNumberValue(value.ID);
			}
			else
			{
				writer.WriteStringValue(value.RawText);
			}
		}
	}
	[JsonConverter(typeof(ValueBaseConverter))]
	public struct ValueBase
	{
		public float Value;

		public ValueMode Mode;

		public bool FromDefault;

		public static readonly ValueBase Unchanged = new ValueBase(1f, ValueMode.Rel, fromDefault: true);

		public static readonly ValueBase Zero = new ValueBase(0f, ValueMode.Abs, fromDefault: false);

		public ValueBase(float value = 1f, ValueMode mode = ValueMode.Rel, bool fromDefault = true)
		{
			Value = value;
			Mode = mode;
			FromDefault = fromDefault;
		}

		public readonly float GetAbsValue(float maxValue, float currentValue)
		{
			if (Mode == ValueMode.Rel)
			{
				return FromDefault ? (currentValue * Value) : (maxValue * Value);
			}
			return Value;
		}

		public readonly float GetAbsValue(float baseValue)
		{
			return (Mode == ValueMode.Abs) ? Value : (baseValue * Value);
		}

		public readonly int GetAbsValue(int maxValue, int currentValue)
		{
			return (int)Math.Round(GetAbsValue((float)maxValue, (float)currentValue));
		}

		public readonly int GetAbsValue(int baseValue)
		{
			return (int)Math.Round(GetAbsValue((float)baseValue));
		}

		public override readonly string ToString()
		{
			return $"[Mode: {Mode}, Value: {Value}]";
		}
	}
	public enum ValueMode
	{
		Rel,
		Abs
	}
	public sealed class ValueBaseConverter : JsonConverter<ValueBase>
	{
		public override bool HandleNull => false;

		public override bool CanConvert(Type objectType)
		{
			return objectType == typeof(ValueBase);
		}

		public override ValueBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			switch (reader.TokenType)
			{
			case JsonTokenType.Number:
				return new ValueBase(reader.GetSingle(), ValueMode.Abs);
			case JsonTokenType.StartObject:
			{
				ValueBase result3 = default(ValueBase);
				while (reader.Read())
				{
					if (reader.TokenType == JsonTokenType.EndObject)
					{
						return result3;
					}
					if (reader.TokenType != JsonTokenType.PropertyName)
					{
						throw new JsonException("Expected PropertyName token");
					}
					string @string = reader.GetString();
					reader.Read();
					switch (@string.ToLowerInvariant())
					{
					case "value":
						result3.Value = reader.GetSingle();
						break;
					case "mode":
					{
						if (Enum.TryParse<ValueMode>(reader.GetString(), out var result4))
						{
							result3.Mode = result4;
						}
						break;
					}
					case "fromdefault":
						result3.FromDefault = reader.GetBoolean();
						break;
					}
				}
				throw new JsonException("Expected EndObject token");
			}
			case JsonTokenType.String:
			{
				string text = reader.GetString()?.Trim();
				if (string.IsNullOrEmpty(text))
				{
					throw new JsonException("BoolBase string value is null or empty!");
				}
				bool fromDefault = false;
				if (text.EndsWith("of default", StringComparison.OrdinalIgnoreCase))
				{
					fromDefault = true;
					string text2 = text;
					text = text2.Substring(0, text2.Length - 10).TrimEnd();
				}
				if (text.EndsWith("%", StringComparison.InvariantCulture))
				{
					string text2 = text;
					if (float.TryParse(text2.Substring(0, text2.Length - 1).TrimEnd(), NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var result))
					{
						return new ValueBase(result / 100f, ValueMode.Rel, fromDefault);
					}
				}
				if (text.EqualsAny(true, "Unchanged", "Ignore", "Keep", "Original", "KeepOriginal"))
				{
					return new ValueBase(1f, ValueMode.Rel, fromDefault: false);
				}
				if (float.TryParse(text, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var result2))
				{
					return new ValueBase(result2, ValueMode.Abs);
				}
				throw new JsonException("Cannot parse ValueBase string: " + text + "! Are you sure it's in right format?");
			}
			default:
				throw new JsonException($"ValueBaseJson type: {reader.TokenType} is not implemented!");
			}
		}

		public override void Write(Utf8JsonWriter writer, ValueBase value, JsonSerializerOptions options)
		{
			switch (value.Mode)
			{
			case ValueMode.Rel:
			{
				if (Mathf.Approximately(value.Value, 1f))
				{
					writer.WriteStringValue("Unchanged");
					break;
				}
				string format = (value.FromDefault ? "{0}% of default" : "{0}%");
				writer.WriteStringValue(string.Format(format, value.Value * 100f));
				break;
			}
			case ValueMode.Abs:
				writer.WriteStringValue(value.Value.ToString());
				break;
			}
			writer.WriteCommentValue("ValueBase");
		}
	}
}
namespace AmorLib.Utils.Extensions
{
	public static class CollectionExtensions
	{
		public static TValue GetOrAddNew<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key) where TValue : new()
		{
			if (!dict.TryGetValue(key, out TValue value))
			{
				value = (dict[key] = new TValue());
			}
			return value;
		}

		public static void ForEachValue<TKey, TValue>(this IDictionary<TKey, TValue> dict, Action<TValue> action) where TKey : notnull
		{
			foreach (TValue value in dict.Values)
			{
				action(value);
			}
		}

		public static bool AnyAllValues<TKey, TCollection, TValue>(this IDictionary<TKey, TCollection> dict, Func<TValue, bool> predicate) where TCollection : IEnumerable<TValue>
		{
			foreach (TCollection value in dict.Values)
			{
				if (value.Any(predicate))
				{
					return true;
				}
			}
			return false;
		}

		public static TValue? FirstOrDefaultAllValues<TKey, TCollection, TValue>(this IDictionary<TKey, TCollection> dict, Func<TValue, bool> predicate) where TCollection : IEnumerable<TValue>
		{
			foreach (TCollection value in dict.Values)
			{
				foreach (TValue item in value)
				{
					if (predicate(item))
					{
						return item;
					}
				}
			}
			return default(TValue);
		}
	}
	public static class GameObjectPlusExtensions
	{
		public static bool TryAndGetComponent<T>(this GameObject go, out T component)
		{
			component = go.GetComponent<T>();
			return component != null;
		}

		public static T AddOrGetComponent<T>(this GameObject go) where T : Component
		{
			if (!go.TryAndGetComponent<T>(out var component))
			{
				return go.AddComponent<T>();
			}
			return component;
		}

		public static string GetFullPath(this GameObject go)
		{
			StringBuilder stringBuilder = new StringBuilder(((Object)go).name);
			Transform parent = go.transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				stringBuilder.Insert(0, ((Object)parent).name + "/");
				parent = parent.parent;
			}
			return stringBuilder.ToString();
		}

		public static uint PostWithCleanup(this CellSoundPlayer soundPlayer, uint eventID, Vector3 pos, uint in_uFlags = 1u)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return soundPlayer.Post(eventID, pos, in_uFlags, EventCallback.op_Implicit((Action<Object, AkCallbackType, AkCallbackInfo>)SoundDoneCallback), (Object)(object)soundPlayer);
		}

		private static void SoundDoneCallback(Object in_pCookie, AkCallbackType in_type, AkCallbackInfo callbackInfo)
		{
			CellSoundPlayer val = ((Il2CppObjectBase)in_pCookie).Cast<CellSoundPlayer>();
			if (val != null)
			{
				val.Recycle();
			}
		}

		public static bool IsWithinSqrDistance(this Vector3 a, Vector3 b, float threshold, out float sqrDistance)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = a - b;
			sqrDistance = ((Vector3)(ref val)).sqrMagnitude;
			return sqrDistance <= threshold;
		}
	}
	public static class PluginInfoExtensions
	{
		public static bool VersionEquals(this PluginInfo pluginInfo, string verison)
		{
			int? num = CompareVersion(pluginInfo, verison);
			return num.HasValue && num.GetValueOrDefault() == 0;
		}

		public static bool VersionExceeds(this PluginInfo pluginInfo, string version)
		{
			int? num = CompareVersion(pluginInfo, version);
			return num.HasValue && num.GetValueOrDefault() > 0;
		}

		public static bool VersionAtLeast(this PluginInfo pluginInfo, string version)
		{
			int? num = CompareVersion(pluginInfo, version);
			return num.HasValue && num.GetValueOrDefault() >= 0;
		}

		private static int? CompareVersion(PluginInfo pluginInfo, string verison)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			object obj;
			if (pluginInfo == null)
			{
				obj = null;
			}
			else
			{
				BepInPlugin metadata = pluginInfo.Metadata;
				obj = ((metadata != null) ? metadata.Version : null);
			}
			if ((Version)obj == (Version)null)
			{
				Logger.Error("PluginInfo or Version.Metadata is null");
				return null;
			}
			Match match = Regex.Match(verison, "^(\\d+)\\.(\\d+)\\.(\\d+)$");
			if (!match.Success)
			{
				Logger.Error("Version string format is incorrect");
				return null;
			}
			int num = int.Parse(match.Groups[1].Value);
			int num2 = int.Parse(match.Groups[2].Value);
			int num3 = int.Parse(match.Groups[3].Value);
			return pluginInfo.Metadata.Version.CompareTo(new Version(num, num2, num3, (string)null, (string)null));
		}
	}
	public static class StringExtensions
	{
		public static bool EqualsAny(this string input, bool ignoreCase = false, params string[] args)
		{
			StringComparison comparisonType = (ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
			foreach (string value in args)
			{
				if (input.Equals(value, comparisonType))
				{
					return true;
				}
			}
			return false;
		}

		public static LocaleText ToLocaleText(this string input)
		{
			return new LocaleText(input);
		}
	}
}
namespace AmorLib.Patches.SNet
{
	[HarmonyPatch(typeof(CheckpointManager), "OnStateChange")]
	internal static class Patch_CheckpointState
	{
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		public static void Post_CheckpointStateChange(pCheckpointState newState)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)newState.lastInteraction == 2)
			{
				SNetEvents.CheckpointReloaded();
			}
		}
	}
	[HarmonyPatch(typeof(SNet_SyncManager), "OnRecallDone")]
	internal static class Patch_OnRecallDone
	{
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		private static void Post_RecallDone()
		{
			SNetEvents.RecallDone();
		}
	}
	[HarmonyPatch(typeof(SNet_Capture))]
	internal static class Patch_SNet_Capture
	{
		[HarmonyPatch("TriggerCapture")]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		private static void Pre_TriggerCapture(SNet_Capture __instance)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			SNetEvents.BufferCaptured(__instance.PrimedBufferType);
		}

		[HarmonyPatch("RecallBuffer")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		private static void Post_RecallBuffer(SNet_Capture __instance, eBufferType bufferType)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.IsRecalling)
			{
				SNetEvents.BufferRecalled(bufferType);
			}
		}
	}
}
namespace AmorLib.Patches.LevelGen
{
	[HarmonyPatch]
	internal static class BuilderPatches
	{
		[HarmonyPatch(typeof(Builder), "BuildDone")]
		[HarmonyPostfix]
		[HarmonyBefore(new string[] { "dev.gtfomodding.gtfo-api" })]
		[HarmonyWrapSafe]
		private static void BuildDone_Early()
		{
			LevelEvents.BuildDoneEarly();
		}

		[HarmonyPatch(typeof(Builder), "BuildDone")]
		[HarmonyPostfix]
		[HarmonyAfter(new string[] { "dev.gtfomodding.gtfo-api" })]
		[HarmonyWrapSafe]
		private static void BuildDone_Late()
		{
			LevelEvents.BuildDoneLate();
		}
	}
	[HarmonyPatch(typeof(LG_BuildZoneLightsJob), "Build")]
	internal static class LightsPatches
	{
		[HarmonyPrefix]
		[HarmonyPriority(600)]
		[HarmonyWrapSafe]
		private static void Pre_ZoneBuild(LG_BuildZoneLightsJob __instance, out List<LightWorker>? __state)
		{
			LG_Zone zone = __instance.m_zone;
			if ((Object)(object)zone == (Object)null)
			{
				__state = null;
				return;
			}
			__state = new List<LightWorker>();
			Enumerator<AIG_CourseNode> enumerator = zone.m_courseNodes.GetEnumerator();
			while (enumerator.MoveNext())
			{
				AIG_CourseNode current = enumerator.Current;
				foreach (LG_Light componentsInChild in ((Component)current.m_area).GetComponentsInChildren<LG_Light>(false))
				{
					__state.Add(new LightWorker(zone, current, componentsInChild, ((Object)componentsInChild).GetInstanceID(), componentsInChild.m_intensity));
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPriority(600)]
		[HarmonyWrapSafe]
		private static void Post_ZoneBuild(LG_BuildZoneLightsJob __instance, bool __result, List<LightWorker>? __state)
		{
			if ((Object)(object)__instance.m_zone == (Object)null || !__result || __state == null)
			{
				return;
			}
			foreach (LightWorker item in __state)
			{
				item.Setup();
				LightAPI.AllLightsMap.TryAdd(item.InstanceID, item);
			}
		}
	}
	[HarmonyPatch]
	internal static class TerminalPatches
	{
		private static readonly Dictionary<(int, int, int), LG_ComputerTerminal> ReactorTerminals;

		static TerminalPatches()
		{
			ReactorTerminals = new Dictionary<(int, int, int), LG_ComputerTerminal>();
			LevelAPI.OnAfterBuildBatch += OnAfterBatchBuild;
			LevelAPI.OnLevelCleanup += OnLevelCleanup;
		}

		private static void OnAfterBatchBuild(BatchName batch)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			if ((int)batch != 47)
			{
				return;
			}
			foreach (KeyValuePair<(int, int, int), LG_ComputerTerminal> reactorTerminal in ReactorTerminals)
			{
				if (reactorTerminal.Key.TryGetZone(out LG_Zone zone))
				{
					zone.TerminalsSpawnedInZone.Add(reactorTerminal.Value);
					Logger.Debug("Appended reactor terminal to its TerminalsSpawnedInZone");
				}
			}
		}

		private static void OnLevelCleanup()
		{
			ReactorTerminals.Clear();
		}

		[HarmonyPatch(typeof(LG_ComputerTerminalCommandInterpreter), "ReceiveCommand")]
		[HarmonyPrefix]
		[HarmonyPriority(600)]
		[HarmonyWrapSafe]
		private static void HiddenCommandExecutionFix(LG_ComputerTerminalCommandInterpreter __instance, ref TERM_Command cmd)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			if (((Il2CppArrayBase<TERM_Command>)(object)LG_ComputerTerminalCommandInterpreter.m_alwaysHiddenCommands).Contains(cmd))
			{
				return;
			}
			TERM_Command val = cmd;
			TERM_Command val2 = val;
			if ((int)val2 <= 6)
			{
				if ((int)val2 == 0 || val2 - 5 <= 1)
				{
					return;
				}
			}
			else if (val2 - 10 <= 1 || (int)val2 == 16 || (int)val2 == 31)
			{
				return;
			}
			if (__instance.m_terminal.CommandIsHidden(cmd))
			{
				cmd = (TERM_Command)10;
			}
		}

		[HarmonyPatch(typeof(LG_WardenObjective_Reactor), "Start")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		private static void CustomReactorTerminalFix(LG_WardenObjective_Reactor __instance)
		{
			if (!((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("FlowGeos") && !((Object)(object)__instance.m_terminalPrefab != (Object)null))
			{
				Logger.Info("Resolving terminal prefab for reactor");
				GameObject loadedAsset = AssetAPI.GetLoadedAsset<GameObject>("Assets/AssetPrefabs/Complex/Generic/FunctionMarkers/Terminal_Floor.prefab");
				if ((Object)(object)loadedAsset == (Object)null)
				{
					Logger.Error("Failed to find terminal prefab loaded asset?");
				}
				else
				{
					__instance.m_terminalPrefab = loadedAsset;
				}
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		private static bool ReactorTerminalSpawnNodeFix(LG_ComputerTerminal __instance, ref AIG_CourseNode __result)
		{
			if ((Object)(object)__instance.ConnectedReactor != (Object)null && __instance.m_terminalItem.SpawnNode == null)
			{
				__result = __instance.ConnectedReactor.SpawnNode;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(LG_WardenObjective_Reactor), "GenericObjectiveSetup")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		private static void ReactorTerminalInZoneFix(LG_WardenObjective_Reactor __instance)
		{
			if (__instance.SpawnNode.m_zone.TerminalsSpawnedInZone != null && (Object)(object)__instance.m_terminal != (Object)null)
			{
				ReactorTerminals.Add(__instance.SpawnNode.m_zone.ToIntTuple(), __instance.m_terminal);
			}
		}
	}
}
namespace AmorLib.Networking
{
	public struct LowResColor
	{
		public byte r;

		public byte g;

		public byte b;

		public byte a;

		private static Color _color = Color.black;

		public static implicit operator Color(LowResColor lowResColor)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			_color.r = (float)(int)lowResColor.r / 255f;
			_color.g = (float)(int)lowResColor.g / 255f;
			_color.b = (float)(int)lowResColor.b / 255f;
			_color.a = (float)(int)lowResColor.a / 255f;
			return _color;
		}

		public static implicit operator LowResColor(Color color)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			LowResColor result = default(LowResColor);
			result.r = (byte)(color.r * 255f);
			result.g = (byte)(color.g * 255f);
			result.b = (byte)(color.b * 255f);
			result.a = (byte)(color.a * 255f);
			return result;
		}
	}
	public static class StateReplicatorManager
	{
	}
	public abstract class SyncedEvent<S> where S : struct
	{
		public delegate void ReceiveHandler(S packet);

		public abstract string Prefix { get; }

		public abstract string GUID { get; }

		public bool IsSetup { get; private set; } = false;


		public string EventName { get; private set; } = string.Empty;


		public event ReceiveHandler? OnReceive;

		public event ReceiveHandler? OnReceiveLocal;

		public void Setup()
		{
			if (!IsSetup)
			{
				EventName = "SE-" + Prefix + "-" + GUID;
				NetworkAPI.RegisterEvent<S>(EventName, (Action<ulong, S>)ReceiveClient_Callback);
				IsSetup = true;
			}
		}

		public void Send(S packetData, SNet_Player? target = null, SNet_ChannelType priority = 4)
		{
			//IL_0024: 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)
			if (target != null)
			{
				NetworkAPI.InvokeEvent<S>(EventName, packetData, target, priority);
			}
			else
			{
				NetworkAPI.InvokeEvent<S>(EventName, packetData, priority);
			}
			ReceiveLocal_Callback(packetData);
		}

		private void ReceiveLocal_Callback(S packet)
		{
			ReceiveLocal(packet);
			this.OnReceiveLocal?.Invoke(packet);
		}

		private void ReceiveClient_Callback(ulong sender, S packet)
		{
			Receive(packet);
			this.OnReceive?.Invoke(packet);
		}

		protected virtual void ReceiveLocal(S packet)
		{
		}

		protected virtual void Receive(S packet)
		{
		}
	}
	public abstract class SyncedEventMasterOnly<S> : SyncedEvent<S> where S : struct
	{
		public void Send(S packet, SNet_ChannelType priority = 4)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!SNet.IsMaster)
			{
				Send(packet, SNet.Master, priority);
			}
			else
			{
				Receive(packet);
			}
		}
	}
}
namespace AmorLib.Networking.StateReplicators
{
	public struct Packet
	{
		public uint replicatorID;

		public PacketAction action;
	}
	public enum PacketAction : byte
	{
		Created,
		Destroyed,
		SyncRequest
	}
	internal sealed class ReplicatorHandshake
	{
		public delegate void ClientRequestedSyncDel(SNet_Player requestedPlayer);

		private readonly Dictionary<uint, (bool SetupOnHost, bool SetupOnClient)> _lookup = new Dictionary<uint, (bool, bool)>();

		public string EventName { get; private set; }

		public bool IsReadyToSync { get; private set; }

		public event ClientRequestedSyncDel? OnClientSyncRequested;

		public ReplicatorHandshake(string eventName)
		{
			EventName = eventName;
			NetworkAPI.RegisterEvent<Packet>(EventName, (Action<ulong, Packet>)OnSyncAction);
			SNetEvents.OnRecallDone += OnRecallDone;
		}

		private void OnRecallDone()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			bool flag = default(bool);
			BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(42, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Handshake :: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(EventName);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", Client sending sync request");
			}
			Logger.Warn(val);
			ClientSyncRequest();
		}

		private void ClientSyncRequest()
		{
			if (SNet.IsMaster)
			{
				return;
			}
			foreach (uint key in _lookup.Keys)
			{
				NetworkAPI.InvokeEvent<Packet>(EventName, new Packet
				{
					replicatorID = key,
					action = PacketAction.SyncRequest
				}, SNet.Master, (SNet_ChannelType)2);
			}
		}

		public void Reset()
		{
			_lookup.Clear();
		}

		private void OnSyncAction(ulong sender, Packet packet)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			if (!SNet.IsMaster && sender == SNet.Master.Lookup)
			{
				if (packet.action != PacketAction.SyncRequest)
				{
					SetHostState(packet.replicatorID, packet.action == PacketAction.Created);
				}
				else
				{
					Logger.Warn("Handshake :: OnSyncAction host sync request has no implementation");
				}
			}
			else
			{
				if (!SNet.IsMaster)
				{
					return;
				}
				bool flag = default(bool);
				switch (packet.action)
				{
				case PacketAction.Created:
					SetClientState(packet.replicatorID, isSetup: true);
					break;
				case PacketAction.Destroyed:
					SetClientState(packet.replicatorID, isSetup: false);
					break;
				case PacketAction.SyncRequest:
				{
					SNet_Player requestedPlayer = default(SNet_Player);
					if (!SNet.TryGetPlayer(sender, ref requestedPlayer))
					{
						BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(45, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Handshake :: Cannot find player from sender: ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ulong>(sender);
						}
						Logger.Error(val);
					}
					else
					{
						this.OnClientSyncRequested?.Invoke(requestedPlayer);
					}
					break;
				}
				default:
				{
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(35, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Handshake :: Unknown packet action ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<PacketAction>(packet.action);
					}
					Logger.Error(val);
					break;
				}
				}
			}
		}

		public void UpdateCreated(uint id)
		{
			if (SNet.IsInLobby)
			{
				if (SNet.IsMaster)
				{
					SetHostState(id, isSetup: true);
					NetworkAPI.InvokeEvent<Packet>(EventName, new Packet
					{
						replicatorID = id,
						action = PacketAction.Created
					}, (SNet_ChannelType)2);
				}
				else if (SNet.HasMaster)
				{
					SetClientState(id, isSetup: true);
					NetworkAPI.InvokeEvent<Packet>(EventName, new Packet
					{
						replicatorID = id,
						action = PacketAction.Created
					}, SNet.Master, (SNet_ChannelType)2);
				}
				else
				{
					Logger.Error("Handshake :: MASTER is NULL in lobby; this should NOT happen!!");
				}
			}
			else
			{
				Logger.Error("Handshake :: Session LifeTimeType StateReplicator cannot be created without lobby!");
			}
		}

		public void UpdateDestroyed(uint id)
		{
			if (SNet.IsInLobby)
			{
				if (SNet.IsMaster)
				{
					SetHostState(id, isSetup: true);
					NetworkAPI.InvokeEvent<Packet>(EventName, new Packet
					{
						replicatorID = id,
						action = PacketAction.Destroyed
					}, (SNet_ChannelType)2);
				}
				else if (SNet.HasMaster)
				{
					SetClientState(id, isSetup: true);
					NetworkAPI.InvokeEvent<Packet>(EventName, new Packet
					{
						replicatorID = id,
						action = PacketAction.Destroyed
					}, SNet.Master, (SNet_ChannelType)2);
				}
				else
				{
					Logger.Error("Handshake :: MASTER is NULL in lobby; this should NOT happen!!");
				}
			}
			else
			{
				Logger.Error("Handshake :: Session LifeTimeType StateReplicator cannot be created without lobby!");
			}
		}

		private void SetHostState(uint id, bool isSetup)
		{
			if (_lookup.TryGetValue(id, out (bool, bool) value))
			{
				value.Item1 = isSetup;
			}
			else
			{
				_lookup[id] = new(bool, bool)
				{
					Item1 = isSetup
				};
			}
			UpdateSyncState(id);
		}

		private void SetClientState(uint id, bool isSetup)
		{
			if (_lookup.TryGetValue(id, out (bool, bool) value))
			{
				value.Item2 = isSetup;
			}
			else
			{
				_lookup[id] = new(bool, bool)
				{
					Item2 = isSetup
				};
			}
			UpdateSyncState(id);
		}

		private void UpdateSyncState(uint id)
		{
			bool isReadyToSync = IsReadyToSync;
			IsReadyToSync = _lookup.TryGetValue(id, out (bool, bool) value) && value.Item1 && value.Item2;
			if (IsReadyToSync && IsReadyToSync != isReadyToSync && SNet.HasMaster && !SNet.IsMaster)
			{
				NetworkAPI.InvokeEvent<Packet>(EventName, new Packet
				{
					replicatorID = id,
					action = PacketAction.SyncRequest
				}, SNet.Master, (SNet_ChannelType)2);
			}
		}
	}
	public enum Size
	{
		State4Byte = 4,
		State8Byte = 8,
		State16Byte = 16,
		State32Byte = 32,
		State48Byte = 48,
		State64Byte = 64,
		State80Byte = 80,
		State96Byte = 96,
		State128Byte = 128,
		State196Byte = 196,
		State256Byte = 256
	}
	internal delegate void OnReceiveDel<S>(ulong sender, uint replicatorID, S newState) where S : struct;
	internal interface IReplicatorEvent<S>
	{
		string EventName { get; }

		bool IsRegistered { get; }

		void Invoke(uint replicatorID, S data, SNet_Player? target = null, SNet_ChannelType priority = 2);
	}
	internal interface IStatePayload
	{
		uint ID { get; set; }

		S Get<S>(Size size) where S : struct;

		void Set<S>(S stateData, Size size) where S : struct;
	}
	internal class ReplicatorPayload<S, P> : IReplicatorEvent<S> where S : struct where P : struct, IStatePayload
	{
		private readonly Size _payloadSize;

		public string EventName { get; private set; } = string.Empty;


		public bool IsRegistered => NetworkAPI.IsEventRegistered(EventName);

		public ReplicatorPayload(Size size, string eventName, OnReceiveDel<S> onReceiveCallback)
		{
			OnReceiveDel<S> onReceiveCallback2 = onReceiveCallback;
			base..ctor();
			ReplicatorPayload<S, P> replicatorPayload = this;
			NetworkAPI.RegisterEvent<P>(eventName, (Action<ulong, P>)delegate(ulong sender, P payload)
			{
				onReceiveCallback2?.Invoke(sender, payload.ID, payload.Get<S>(replicatorPayload._payloadSize));
			});
			EventName = eventName;
			_payloadSize = size;
		}

		public void Invoke(uint replicatorID, S data, SNet_Player? target, SNet_ChannelType priority)
		{
			//IL_0054: 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)
			P val = new P
			{
				ID = replicatorID
			};
			val.Set(data, _payloadSize);
			if ((Object)(object)target != (Object)null)
			{
				NetworkAPI.InvokeEvent<P>(EventName, val, target, priority);
			}
			else
			{
				NetworkAPI.InvokeEvent<P>(EventName, val, priority);
			}
		}
	}
	internal struct StatePayloadBytes : IStatePayload
	{
		public unsafe fixed byte PayloadBytes[256];

		public uint ID { get; set; }

		public unsafe S Get<S>(Size size) where S : struct
		{
			byte[] array = new byte[(int)size];
			fixed (byte* ptr = PayloadBytes)
			{
				Marshal.Copy((IntPtr)ptr, array, 0, (int)size);
			}
			return FromBytes<S>(array);
		}

		public unsafe void Set<S>(S stateData, Size size) where S : struct
		{
			byte[] array = ToBytes(stateData);
			if (array.Length > (int)size)
			{
				throw new ArgumentException($"Data size {array.Length} exceeds payload size {size}, unable to serialize {"S"}!");
			}
			fixed (byte* ptr = PayloadBytes)
			{
				Marshal.Copy(array, 0, (IntPtr)ptr, array.Length);
				for (int i = array.Length; i < (int)size; i++)
				{
					ptr[i] = 0;
				}
			}
		}

		private static byte[] ToBytes<S>(S data) where S : struct
		{
			int num = Marshal.SizeOf<S>();
			byte[] array = new byte[num];
			IntPtr intPtr = Marshal.AllocHGlobal(num);
			try
			{
				Marshal.StructureToPtr(data, intPtr, fDeleteOld: false);
				Marshal.Copy(intPtr, array, 0, num);
				return array;
			}
			finally
			{
				Marshal.FreeHGlobal(intPtr);
			}
		}

		private static S FromBytes<S>(byte[] arr) where S : struct
		{
			IntPtr intPtr = Marshal.AllocHGlobal(arr.Length);
			try
			{
				Marshal.Copy(arr, 0, intPtr, arr.Length);
				return Marshal.PtrToStructure<S>(intPtr);
			}
			finally
			{
				Marshal.FreeHGlobal(intPtr);
			}
		}
	}
	public enum LifeTimeType
	{
		Permanent,
		Session
	}
	public sealed class StateReplicator<S> where S : struct
	{
		internal readonly Dictionary<eBufferType, S> _recallStateSnapshots = new Dictionary<eBufferType, S>();

		public static readonly string Name;

		public static readonly string HashName;

		public static readonly string ClientRequestEventName;

		public static readonly string HostSetStateEventName;

		public static readonly string HostSetRecallStateEventName;

		public static readonly string HandshakeEventName;

		public static readonly int StateSize;

		public static readonly Size StateSizeType;

		private static readonly IReplicatorEvent<S>? _clientRequestEvent;

		private static readonly IReplicatorEvent<S>? _hostSetStateEvent;

		private static readonly IReplicatorEvent<S>? _hostSetRecallStateEvent;

		private static readonly ReplicatorHandshake? _handshake;

		internal static readonly Dictionary<uint, StateReplicator<S>> _replicators;

		public bool IsValid => ID != 0;

		public bool IsInvalid => ID == 0;

		public uint ID { get; private set; }

		public LifeTimeType LifeTime { get; private set; }

		public S State { get; private set; }

		public S LastState { get; private set; }

		public bool ClientSendStateAllowed { get; set; } = true;


		public bool CanSendToClient => SNet.IsInLobby && SNet.IsMaster;

		public bool CanSendToHost => SNet.IsInLobby && !SNet.IsMaster && SNet.HasMaster && ClientSendStateAllowed;

		public event Action<S, S, bool>? OnStateChanged;

		public void SetState(S state)
		{
			if (!IsInvalid)
			{
				DoSync(state);
			}
		}

		public void SetStateUnsynced(S state)
		{
			if (!IsInvalid)
			{
				LastState = state;
				State = state;
			}
		}

		public void Unload()
		{
			if (IsValid)
			{
				_replicators.Remove(ID);
				_recallStateSnapshots.Clear();
				_handshake?.UpdateDestroyed(ID);
				ID = 0u;
			}
		}

		private void DoSync(S newState)
		{
			if (IsValid)
			{
				if (CanSendToClient)
				{
					_hostSetStateEvent?.Invoke(ID, newState, null, (SNet_ChannelType)2);
					Internal_ChangeState(newState, isRecall: false);
				}
				else if (CanSendToHost)
				{
					_clientRequestEvent?.Invoke(ID, newState, SNet.Master, (SNet_ChannelType)2);
				}
			}
		}

		private void Internal_ChangeState(S state, bool isRecall)
		{
			if (!IsInvalid)
			{
				S state2 = State;
				State = state;
				LastState = state2;
				this.OnStateChanged?.Invoke(state2, state, isRecall);
			}
		}

		private void SendDropInState(SNet_Player target)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			if (IsInvalid || (Object)(object)target == (Object)null)
			{
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(35, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("IsInvalid: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(IsInvalid);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("SendDropInState");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" :: Target was null? ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>((Object)(object)target == (Object)null);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("?");
				}
				Logger.Error(val);
			}
			else
			{
				_hostSetRecallStateEvent?.Invoke(ID, State, target, (SNet_ChannelType)2);
			}
		}

		public void ClearAllRecallSnapshot()
		{
			if (!IsInvalid)
			{
				_recallStateSnapshots.Clear();
			}
		}

		private void SaveSnapshot(eBufferType type)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!IsInvalid)
			{
				_recallStateSnapshots[type] = State;
			}
		}

		private void RestoreSnapshot(eBufferType type)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (!IsValid || !CanSendToClient)
			{
				return;
			}
			if (_recallStateSnapshots.TryGetValue(type, out var value))
			{
				_hostSetRecallStateEvent?.Invoke(ID, value, null, (SNet_ChannelType)2);
				Internal_ChangeState(value, isRecall: true);
				return;
			}
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(31, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("RestoreSnapshot");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" :: There was no snapshot for ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<eBufferType>(type);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("?");
			}
			Logger.Error(val);
		}

		static StateReplicator()
		{
			_replicators = new Dictionary<uint, StateReplicator<S>>();
			Name = typeof(S).Name;
			StateSize = Marshal.SizeOf(typeof(S));
			StateSizeType = GetSizeType(StateSize);
			using MD5 mD = MD5.Create();
			byte[] inArray = mD.ComputeHash(Encoding.UTF8.GetBytes(typeof(S).FullName));
			HashName = Convert.ToBase64String(inArray);
			ClientRequestEventName = "SRcr-" + Name + "-" + HashName;
			HostSetStateEventName = "SRhs-" + Name + "-" + HashName;
			HostSetRecallStateEventName = "SRre-" + Name + "-" + HashName;
			HandshakeEventName = "RH-" + Name + "-" + HashName;
			_clientRequestEvent = CreatePayloadEvent(ClientRequestEventName, ClientRequestEventCallback);
			_hostSetStateEvent = CreatePayloadEvent(HostSetStateEventName, HostSetStateEventCallback);
			_hostSetRecallStateEvent = CreatePayloadEvent(HostSetRecallStateEventName, HostSetRecallStateEventCallback);
			_handshake = CreateHandshakeEvent();
			SNetEvents.OnBufferCapture += BufferStored;
			SNetEvents.OnBufferRecall += BufferRecalled;
			LevelAPI.OnLevelCleanup += OnLevelCleanup;
		}

		public static StateReplicator<S>? Create(uint replicatorID, S startState, LifeTimeType lifeTime)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			if (replicatorID == 0)
			{
				Logger.Error("Replicator ID 0 is reserved for empty!");
				return null;
			}
			if (_replicators.ContainsKey(replicatorID))
			{
				Logger.Error("Replicator ID has already assigned!");
				return null;
			}
			StateReplicator<S> stateReplicator = new StateReplicator<S>
			{
				ID = replicatorID,
				LifeTime = lifeTime,
				State = startState
			};
			switch (lifeTime)
			{
			case LifeTimeType.Permanent:
				Logger.Debug("LifeTime is Permanent :: Handshaking is disabled");
				break;
			case LifeTimeType.Session:
				_handshake?.UpdateCreated(replicatorID);
				break;
			default:
			{
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(21, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("LifeTime ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<LifeTimeType>(lifeTime);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is invalid!");
				}
				Logger.Error(val);
				return null;
			}
			}
			_replicators[replicatorID] = stateReplicator;
			return stateReplicator;
		}

		public static Size GetSizeType(int stateSize)
		{
			Size size = Size.State8Byte;
			foreach (Size value in Enum.GetValues(typeof(Size)))
			{
				if (stateSize <= (int)value && size < value)
				{
					size = value;
					break;
				}
			}
			return size;
		}

		private static IReplicatorEvent<S>? CreatePayloadEvent(string name, OnReceiveDel<S> callback)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			if (NetworkAPI.IsEventRegistered(name))
			{
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(77, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ReplicatorPayload<");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(">.");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("callback");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" failed to initialize: Event name ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is already registered!");
				}
				Logger.Error(val);
				return null;
			}
			return new ReplicatorPayload<S, StatePayloadBytes>(StateSizeType, name, callback);
		}

		private static ReplicatorHandshake? CreateHandshakeEvent()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			if (NetworkAPI.IsEventRegistered(HandshakeEventName))
			{
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(78, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ReplicatorHandshake<");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("> failed to initialize: Event name ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(HandshakeEventName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is already registered!");
				}
				Logger.Error(val);
				return null;
			}
			ReplicatorHandshake replicatorHandshake = new ReplicatorHandshake(HandshakeEventName);
			replicatorHandshake.OnClientSyncRequested += ClientSyncRequested;
			return replicatorHandshake;
		}

		private static void ClientRequestEventCallback(ulong sender, uint replicatorID, S newState)
		{
			if (SNet.IsMaster && _replicators.TryGetValue(replicatorID, out StateReplicator<S> value))
			{
				value.SetState(newState);
			}
		}

		private static void HostSetStateEventCallback(ulong sender, uint replicatorID, S newState)
		{
			if (SNet.HasMaster && SNet.Master.Lookup == sender && _replicators.TryGetValue(replicatorID, out StateReplicator<S> value))
			{
				value.Internal_ChangeState(newState, isRecall: false);
			}
		}

		private static void HostSetRecallStateEventCallback(ulong sender, uint replicatorID, S newState)
		{
			if (SNet.HasMaster && SNet.Master.Lookup == sender && _replicators.TryGetValue(replicatorID, out StateReplicator<S> value))
			{
				value.Internal_ChangeState(newState, isRecall: true);
			}
		}

		private static void ClientSyncRequested(SNet_Player requestedPlayer)
		{
			foreach (StateReplicator<S> value in _replicators.Values)
			{
				if (value.IsValid)
				{
					value.SendDropInState(requestedPlayer);
				}
			}
		}

		private static void BufferStored(eBufferType type)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			foreach (StateReplicator<S> value in _replicators.Values)
			{
				if (value.IsValid)
				{
					value.SaveSnapshot(type);
				}
			}
		}

		private static void BufferRecalled(eBufferType type)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			foreach (StateReplicator<S> value in _replicators.Values)
			{
				if (value.IsValid)
				{
					value.RestoreSnapshot(type);
				}
			}
		}

		private static void OnLevelCleanup()
		{
			UnloadSessionReplicators();
		}

		public static void UnloadSessionReplicators()
		{
			List<uint> list = new List<uint>();
			foreach (StateReplicator<S> value in _replicators.Values)
			{
				if (value.LifeTime == LifeTimeType.Session)
				{
					list.Add(value.ID);
					value.Unload();
				}
			}
			foreach (uint item in list)
			{
				_replicators.Remove(item);
			}
			_handshake?.Reset();
		}
	}
}
namespace AmorLib.Events
{
	public static class LevelEvents
	{
		public static event Action? OnBuildDoneEarly;

		public static event Action? OnBuildDoneLate;

		internal static void BuildDoneEarly()
		{
			SafeInvoke.Invoke(LevelEvents.OnBuildDoneEarly);
		}

		internal static void BuildDoneLate()
		{
			SafeInvoke.Invoke(LevelEvents.OnBuildDoneLate);
		}
	}
	public static class SNetEvents
	{
		public static event Action<eBufferType>? OnBufferCapture;

		public static event Action<eBufferType>? OnBufferRecall;

		public static event Action? OnCheckpointReload;

		public static event Action? OnRecallDone;

		internal static void BufferCaptured(eBufferType bufferType)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			SafeInvoke.Invoke<eBufferType>(SNetEvents.OnBufferCapture, bufferType);
		}

		internal static void BufferRecalled(eBufferType bufferType)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			SafeInvoke.Invoke<eBufferType>(SNetEvents.OnBufferRecall, bufferType);
		}

		internal static void CheckpointReloaded()
		{
			SafeInvoke.Invoke(SNetEvents.OnCheckpointReload);
		}

		internal static void RecallDone()
		{
			SafeInvoke.Invoke(SNetEvents.OnRecallDone);
		}
	}
}
namespace AmorLib.Dependencies
{
	[CallConstructorOnLoad]
	public class InjectLib_Wrapper
	{
		public const string PLUGIN_GUID = "GTFO.InjectLib";

		public static bool IsLoaded { get; private set; }

		public static JsonConverter? InjectLibConverter { get; private set; }

		static InjectLib_Wrapper()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			IsLoaded = false;
			InjectLibConverter = null;
			bool flag = default(bool);
			if (((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("GTFO.InjectLib"))
			{
				try
				{
					IsLoaded = true;
					InjectLibConverter = (JsonConverter)Activator.CreateInstance(typeof(InjectLibConnector));
				}
				catch (Exception ex)
				{
					IsLoaded = false;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(52, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Exception thrown while reading data from InjectLib:\n");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					Logger.Error(val);
				}
			}
			BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(21, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("InjectLib is loaded: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(IsLoaded);
			}
			Logger.Debug(val2);
		}
	}
	[CallConstructorOnLoad]
	public static class PData_Wrapper
	{
		public const string PLUGIN_GUID = "MTFO.Extension.PartialBlocks";

		public static bool IsLoaded { get; private set; }

		public static bool IsInitialized { get; private set; }

		public static bool IsMainBranch { get; private set; }

		public static JsonConverter? PersistentIDConverter { get; private set; }

		static PData_Wrapper()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			IsLoaded = false;
			IsInitialized = false;
			IsMainBranch = false;
			PersistentIDConverter = null;
			bool flag = default(bool);
			if (((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("MTFO.Extension.PartialBlocks", out var value))
			{
				try
				{
					IsLoaded = true;
					IsInitialized = PartialDataManager.Initialized;
					IsMainBranch = value.VersionAtLeast("1.5.2");
					PersistentIDConverter = (JsonConverter)Activator.CreateInstance(typeof(PersistentIDConverter));
				}
				catch (Exception ex)
				{
					IsLoaded = false;
					IsInitialized = false;
					IsMainBranch = false;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(54, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Exception thrown while reading data from PartialData:\n");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					Logger.Error(val);
				}
			}
			BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(81, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("PartialData is loaded and initialized: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(IsLoaded && IsInitialized);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", Version at least \"1.5.2\" (main branch): ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(IsMainBranch);
			}
			Logger.Debug(val2);
			if (IsLoaded && !IsMainBranch)
			{
				Logger.Warn("AWOPartialDataFixer (PartialDataModCompatible) is deprecated, or older version! It will still work but it's recommended to switch to the main branch of PartialData");
			}
		}

		public static bool TryGetGUID(string text, out uint guid)
		{
			if (IsLoaded && IsInitialized && IsMainBranch)
			{
				guid = GetGUID(text);
				return guid != 0;
			}
			guid = 0u;
			return false;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static uint GetGUID(string text)
		{
			uint result = default(uint);
			if (PersistentIDManager.TryGetId(text, ref result))
			{
				return result;
			}
			return 0u;
		}
	}
}
namespace AmorLib.API
{
	public interface ILightModifier
	{
		Color Color { get; set; }

		float Intensity { get; set; }

		bool Enabled { get; set; }

		int Priority { get; }

		bool Active { get; }

		void Set(Color color, float intensity, bool enabled)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			Color = color;
			Intensity = intensity;
			Enabled = enabled;
		}

		bool Register();

		void Remove();
	}
	[CallConstructorOnLoad]
	public static class LightAPI
	{
		internal static readonly ConcurrentDictionary<int, LightWorker> AllLightsMap;

		static LightAPI()
		{
			AllLightsMap = new ConcurrentDictionary<int, LightWorker>();
			LevelAPI.OnAfterBuildBatch += OnAfterZoneLightsBatch;
			LevelAPI.OnLevelCleanup += OnLevelCleanup;
		}

		private static void OnLevelCleanup()
		{
			AllLightsMap.Clear();
		}

		private static void OnAfterZoneLightsBatch(BatchName batch)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if ((int)batch == 61)
			{
				bool flag = default(bool);
				BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(35, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("All LightWorkers are setup. Count: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(AllLightsMap.Count);
				}
				Logger.Debug(val);
			}
		}

		public static LightWorker? GetSpecificLightWorker(int instanceID)
		{
			LightWorker worker;
			return TryGetSpecificLightWorker(instanceID, out worker) ? worker : null;
		}

		public static bool TryGetSpecificLightWorker(int instanceID, [NotNullWhen(true)] out LightWorker? worker)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			if (!AllLightsMap.TryGetValue(instanceID, out worker))
			{
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(65, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to find LightWorker: no LG_Light exists with instance id ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(instanceID);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("!");
				}
				Logger.Error(val);
				return false;
			}
			return true;
		}

		public static void ForEachWorker(this IEnumerable<LightWorker> lightWorkers, Action<LightWorker> action)
		{
			foreach (LightWorker lightWorker in lightWorkers)
			{
				action(lightWorker);
			}
		}

		public static IEnumerable<ILightModifier> AddLightModifiers(this IEnumerable<LightWorker> lightWorkers, Color color, float intensity, bool enabled, int priority = 1000)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return lightWorkers.Select((LightWorker worker) => worker.AddModifier(color, intensity, enabled, priority));
		}

		public static void ForEachMod(this IEnumerable<ILightModifier> lightModifiers, Action<ILightModifier> action)
		{
			foreach (ILightModifier lightModifier in lightModifiers)
			{
				action(lightModifier);
			}
		}

		public static IEnumerable<LightWorker> GetLightWorkersInDimension(params eDimensionIndex[] args)
		{
			eDimensionIndex[] args2 = args;
			return AllLightsMap.Values.Where((LightWorker light) => args2.Contains(light.OwnerZone.DimensionIndex));
		}

		public static IEnumerable<LightWorker> GetLightWorkersInZone(params (int, int, int)[] args)
		{
			(int, int, int)[] args2 = args;
			return AllLightsMap.Values.Where((LightWorker light) => args2.Contains<(int, int, int)>(light.OwnerZone.ToIntTuple()));
		}

		public static IEnumerable<LightWorker> GetLightWorkersInZone(params LG_Zone[] args)
		{
			(int, int, int)[] args2 = args.Select((LG_Zone z) => z.ToIntTuple()).Distinct().ToArray();
			return GetLightWorkersInZone(args2);
		}

		public static IEnumerable<LightWorker> GetLightWorkersInNode(params AIG_CourseNode[] args)
		{
			HashSet<ushort> nodes = args.Select((AIG_CourseNode n) => ((AIG_CourseGraphMember)n).m_searchID).ToHashSet();
			return AllLightsMap.Values.Where((LightWorker light) => nodes.Contains(((AIG_CourseGraphMember)light.SpawnNode).m_searchID));
		}

		public static IEnumerable<LightWorker> GetLightWorkersInRange(Vector3 position, float range)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			float sqrDistance;
			return AllLightsMap.Values.Where((LightWorker light) => light.Position.IsWithinSqrDistance(position, range, out sqrDistance));
		}

		public static IEnumerable<LightWorker> GetLightWorkersInRange(eDimensionIndex dimension, Vector3 position, float range)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			float sqrDistance;
			return AllLightsMap.Values.Where((LightWorker light) => light.OwnerZone.DimensionIndex == dimension && light.Position.IsWithinSqrDistance(position, range, out sqrDistance));
		}
	}
	public static class LightPriority
	{
		public const int Normal = 1000;

		public const int EMP = 2000;
	}
	public class LightWorker
	{
		private class LightModifier : ILightModifier
		{
			private Color _color;

			private float _intensity;

			private bool _enabled;

			private readonly LightWorker _worker;

			public Color Color
			{
				get
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					return _color;
				}
				set
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0003: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: 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_002b: Unknown result type (might be due to invalid IL or missing references)
					if (!(value == _color))
					{
						_color = value;
						if (InUse)
						{
							_worker.ChangeLightColor(_color);
						}
					}
				}
			}

			public float Intensity
			{
				get
				{
					return _intensity;
				}
				set
				{
					if (value != _intensity)
					{
						_intensity = value;
						if (InUse)
						{
							_worker.ChangeLightIntensity(_intensity);
						}
					}
				}
			}

			public bool Enabled
			{
				get
				{
					return _enabled;
				}
				set
				{
					if (value != _enabled)
					{
						_enabled = value;
						if (InUse)
						{
							_worker.SetLightEnabled(_enabled);
						}
					}
				}
			}

			public int Priority { get; }

			public LinkedListNode<LightModifier>? Node { get; set; }

			public bool Active => Node != null && _worker != null;

			private bool InUse => Active && _worker._currentNode == Node;

			public LightModifier(Color color, float intensity, bool enabled, int priority, LightWorker worker)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				_color = color;
				_intensity = intensity;
				_enabled = enabled;
				Priority = priority;
				_worker = worker;
			}

			public bool Register()
			{
				if (_worker == null)
				{
					return false;
				}
				if (Active)
				{
					_worker._priorityDict[Priority].Remove(Node);
				}
				_worker.AddModifier(this);
				return true;
			}

			public void Apply()
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				_worker.ChangeLightColor(_color);
				_worker.ChangeLightIntensity(_intensity);
				_worker.SetLightEnabled(_enabled);
			}

			public void Remove()
			{
				if (Active)
				{
					_worker.RemoveModifier(this);
				}
			}
		}

		public readonly LG_Zone OwnerZone;

		public readonly AIG_CourseNode SpawnNode;

		public readonly LG_Light Light;

		public readonly int InstanceID;

		public readonly float PrefabIntensity;

		public LG_LightAnimator? Animator;

		public Color OrigColor;

		public float OrigIntensity;

		public bool OrigEnabled;

		private readonly SortedDictionary<int, LinkedList<LightModifier>> _priorityDict = new SortedDictionary<int, LinkedList<LightModifier>>();

		private LinkedListNode<LightModifier>? _currentNode;

		public const int OrigPriority = -1000;

		private ILightModifier _origLightMod = null;

		public Vector3 Position => Light.GetPosition();

		public LightWorker(LG_Zone zone, AIG_CourseNode node, LG_Light light, int id, float intensity)
		{
			OwnerZone = zone;
			SpawnNode = node;
			Light = light;
			InstanceID = id;
			PrefabIntensity = intensity;
		}

		internal void Setup()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Animator = ((Component)Light).gameObject.GetComponent<LG_LightAnimator>();
			OrigColor = Light.m_color;
			OrigIntensity = Light.m_intensity;
			OrigEnabled = ((Component)Light).gameObject.active;
			_origLightMod = AddModifier(OrigColor, OrigIntensity, OrigEnabled, -1000);
		}

		public bool IsEMPActive()
		{
			LinkedList<LightModifier> value;
			return _priorityDict.TryGetValue(2000, out value) && value.Count > 0;
		}

		private void ChangeLightColor(Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Light.ChangeColor(color);
		}

		private void ChangeLightIntensity(float intensity)
		{
			Light.ChangeIntensity(intensity);
		}

		private void SetLightEnabled(bool enabled)
		{
			Light.SetEnabled(enabled);
		}

		public bool ToggleLightFlicker(bool enabled)
		{
			if ((Object)(object)Animator == (Object)null)
			{
				return false;
			}
			C_Light c_Light = Light.GetC_Light();
			if (enabled)
			{
				Animator.ResetRamp(c_Light);
			}
			else
			{
				Animator.m_inRamp = false;
				Animator.m_startTime = float.MaxValue;
				Animator.m_absTime = 1f;
				Animator.FeedLight(c_Light);
			}
			return true;
		}

		public ILightModifier AddModifier(Color color, float intensity, bool enabled, int priority = 1000)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			LightModifier lightModifier = new LightModifier(color, intensity, enabled, priority, this);
			AddModifier(lightModifier);
			return lightModifier;
		}

		private void AddModifier(LightModifier modifier)
		{
			LinkedList<LightModifier> orAddNew = _priorityDict.GetOrAddNew(modifier.Priority);
			modifier.Node = orAddNew.AddLast(modifier);
			if (_currentNode == null || _currentNode.Value.Priority <= modifier.Priority)
			{
				_currentNode = modifier.Node;
				modifier.Apply();
			}
		}

		private void RemoveModifier(LightModifier modifier)
		{
			LinkedList<LightModifier> linkedList = _priorityDict[modifier.Priority];
			if (_currentNode != modifier.Node)
			{
				linkedList.Remove(modifier.Node);
				modifier.Node = null;
				return;
			}
			if (modifier.Node.Previous != null)
			{
				_currentNode = modifier.Node.Previous;
			}
			else
			{
				_currentNode = _priorityDict.Values.Last((LinkedList<LightModifier> list) => list.Count > 0).Last;
			}
			linkedList.Remove(modifier.Node);
			modifier.Node = null;
			_currentNode.Value.Apply();
		}

		internal void Reset()
		{
			foreach (LinkedList<LightModifier> value in _priorityDict.Values)
			{
				foreach (LightModifier item in value)
				{
					item.Remove();
				}
			}
			_priorityDict.Clear();
			_origLightMod.Register();
		}
	}
}