Decompiled source of ProgressionGear v1.7.1

ProgressionGear.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CellMenu;
using EOS.BaseClasses;
using EOS.Modules.Expedition;
using ExtraObjectiveSetup.Expedition;
using GTFO.API;
using GTFO.API.JSON.Converters;
using GTFO.API.Utilities;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using LocalProgression;
using LocalProgression.Data;
using Localization;
using MTFO.API;
using Microsoft.CodeAnalysis;
using Player;
using ProgressionGear.Dependencies;
using ProgressionGear.GearToggle;
using ProgressionGear.JSON;
using ProgressionGear.JSON.Converters;
using ProgressionGear.LevelLock;
using ProgressionGear.Patches;
using ProgressionGear.ProgressionLock;
using ProgressionGear.Utils;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ProgressionGear")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ffa4c44bfbbd3677256b09e37e39950017d0a707")]
[assembly: AssemblyProduct("ProgressionGear")]
[assembly: AssemblyTitle("ProgressionGear")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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 ProgressionGear
{
	internal static class Configuration
	{
		private static readonly ConfigEntry<bool> _disableProgression;

		private static readonly ConfigEntry<bool> _toggleBlink;

		private static readonly ConfigFile _configFile;

		private static bool _disabled;

		public static bool DisableProgression => _disableProgression.Value;

		public static bool ToggleBlink => _toggleBlink.Value;

		static Configuration()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			_configFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "ProgressionGear.cfg"), true);
			string text = "Override";
			_disableProgression = _configFile.Bind<bool>(text, "Disable Progression Locks", false, "Disables progression-locking for weapons.");
			_disabled = _disableProgression.Value;
			text = "General Settings";
			_toggleBlink = _configFile.Bind<bool>(text, "Toggle Blink", true, "Enables the blinking effect on gear toggle buttons.");
		}

		public static void Init()
		{
			SafeFileSystemWatcher.Create(_configFile);
			_configFile.ConfigReloaded += OnFileChanged;
		}

		private static void OnFileChanged(object? sender, EventArgs e)
		{
			if (_disabled != DisableProgression)
			{
				_disabled = !_disabled;
				GearLockManager.Current.SetupAllowedGearsForActiveRundown();
			}
		}
	}
	internal static class DinoLogger
	{
		private static ManualLogSource logger = Logger.CreateLogSource("ProgressionGear");

		public static void Log(string format, params object[] args)
		{
			Log(string.Format(format, args));
		}

		public static void Log(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)8, (object)str);
			}
		}

		public static void Warning(string format, params object[] args)
		{
			Warning(string.Format(format, args));
		}

		public static void Warning(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)4, (object)str);
			}
		}

		public static void Error(string format, params object[] args)
		{
			Error(string.Format(format, args));
		}

		public static void Error(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)2, (object)str);
			}
		}

		public static void Debug(string format, params object[] args)
		{
			Debug(string.Format(format, args));
		}

		public static void Debug(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)32, (object)str);
			}
		}
	}
	[BepInPlugin("Dinorush.ProgressionGear", "ProgressionGear", "1.7.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class EntryPoint : BasePlugin
	{
		public const string GUID = "Dinorush.ProgressionGear";

		public const string MODNAME = "ProgressionGear";

		public override void Load()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			if (!MTFOWrapper.HasCustomContent)
			{
				DinoLogger.Error("No MTFO datablocks detected. Not loading ProgressionGear...");
				return;
			}
			MTFOHotReloadAPI.OnHotReload += FixGearInstanceDict;
			Harmony val = new Harmony("ProgressionGear");
			val.PatchAll();
			if (!LocalProgressionWrapper.HasLocalProgression)
			{
				val.PatchAll(typeof(PageRundownPatches_NoLP));
			}
			Configuration.Init();
			GearLockManager.Current.Init();
			GearToggleManager.Current.Init();
			ProgressionLockManager.Current.Init();
			LevelLockManager.Current.Init();
			GameDataAPI.OnGameDataInitialized += ProgressionWrapper.CacheLevelLayouts;
			DinoLogger.Log("Loaded ProgressionGear");
		}

		private static void FixGearInstanceDict()
		{
			GearManager.Current.m_allGearPerInstanceKey.Clear();
			GearManager.Current.OnGearLoadingDone();
		}
	}
}
namespace ProgressionGear.Utils
{
	internal class DictListEnumerator<T> : IEnumerator<T>, IEnumerator, IDisposable
	{
		private readonly IEnumerator<List<T>> _valueEnumerator;

		private List<T>? _curList;

		private int _index;

		private T? _current;

		public T Current => _current;

		object IEnumerator.Current => Current;

		internal DictListEnumerator(Dictionary<string, List<T>> data)
		{
			_valueEnumerator = data.Values.GetEnumerator();
			if (_valueEnumerator.MoveNext())
			{
				_curList = _valueEnumerator.Current;
			}
			_index = -1;
		}

		public void Dispose()
		{
		}

		public bool MoveNext()
		{
			if (_curList == null || ++_index >= _curList.Count)
			{
				if (!_valueEnumerator.MoveNext())
				{
					return false;
				}
				_curList = _valueEnumerator.Current;
				_index = 0;
			}
			_current = _curList[_index];
			return true;
		}

		public void Reset()
		{
			_valueEnumerator.Reset();
			if (_valueEnumerator.MoveNext())
			{
				_curList = _valueEnumerator.Current;
			}
			_index = -1;
		}
	}
	internal static class GearIDRangeExtensions
	{
		public static uint GetOfflineID(this GearIDRange gearIDRange)
		{
			string playfabItemInstanceId = gearIDRange.PlayfabItemInstanceId;
			if (!playfabItemInstanceId.Contains("OfflineGear_ID_"))
			{
				DinoLogger.Error("Find PlayfabItemInstanceId without substring 'OfflineGear_ID_'! " + playfabItemInstanceId);
				return 0u;
			}
			try
			{
				return uint.Parse(playfabItemInstanceId.Substring("OfflineGear_ID_".Length));
			}
			catch
			{
				DinoLogger.Error("Caught exception while trying to parse persistentID of PlayerOfflineGearDB from GearIDRange, which means itemInstanceId could be ill-formated");
				return 0u;
			}
		}
	}
	internal static class StringExtensions
	{
		public static T ToEnum<T>(this string? value, T defaultValue) where T : struct
		{
			if (string.IsNullOrEmpty(value))
			{
				return defaultValue;
			}
			if (!Enum.TryParse<T>(value.Replace(" ", null), ignoreCase: true, out var result))
			{
				return defaultValue;
			}
			return result;
		}
	}
}
namespace ProgressionGear.ProgressionLock
{
	public sealed class GearLockManager
	{
		private struct PriorityLockData
		{
			public int priority;

			public bool locked;

			public bool explicitLock;
		}

		private HashSet<uint>? _whitelistGearIds;

		private readonly HashSet<uint> _blacklistGearIds = new HashSet<uint>();

		private HashSet<uint>? _overrideProgressionIds;

		private bool _useOverrideProgression;

		internal readonly List<(InventorySlot inventorySlot, Dictionary<uint, GearIDRange> loadedGears)> GearSlots = new List<(InventorySlot, Dictionary<uint, GearIDRange>)>
		{
			((InventorySlot)1, new Dictionary<uint, GearIDRange>()),
			((InventorySlot)2, new Dictionary<uint, GearIDRange>()),
			((InventorySlot)10, new Dictionary<uint, GearIDRange>()),
			((InventorySlot)3, new Dictionary<uint, GearIDRange>())
		};

		public static GearLockManager Current { get; private set; } = new GearLockManager();

		public GearManager? VanillaGearManager { get; internal set; }

		public void Init()
		{
			MTFOHotReloadAPI.OnHotReload += SetupAllowedGearsForActiveRundown;
		}

		private void ApplyProgressionLocks()
		{
			GearToggleManager.Current.ResetToggleInfos();
			if (Configuration.DisableProgression)
			{
				return;
			}
			IEnumerator<ProgressionLockData> enumerator = ProgressionLockManager.Current.GetEnumerator();
			Dictionary<uint, PriorityLockData> dictionary = new Dictionary<uint, PriorityLockData>();
			while (enumerator.MoveNext())
			{
				ProgressionLockData current = enumerator.Current;
				if (current.RundownIDs.Length != 0 && !current.RundownIDs.Contains(ProgressionWrapper.CurrentRundownID))
				{
					continue;
				}
				foreach (uint offlineID in current.OfflineIDs)
				{
					PriorityLockData value = new PriorityLockData
					{
						priority = current.Priority,
						locked = IsGearLocked(current),
						explicitLock = IsLockExplicit(current)
					};
					if (!dictionary.TryGetValue(offlineID, out var value2) || ((!value2.explicitLock || value.explicitLock) && value2.priority <= value.priority))
					{
						dictionary[offlineID] = value;
					}
				}
			}
			if (_useOverrideProgression)
			{
				if (_overrideProgressionIds != null)
				{
					foreach (uint overrideProgressionId in _overrideProgressionIds)
					{
						dictionary.Remove(overrideProgressionId);
					}
				}
				else
				{
					dictionary.Clear();
				}
			}
			foreach (KeyValuePair<uint, PriorityLockData> item in dictionary.Where((KeyValuePair<uint, PriorityLockData> kv) => kv.Value.locked))
			{
				_blacklistGearIds.Add(item.Key);
				GearToggleManager.Current.RemoveFromToggleInfos(item.Key);
			}
		}

		public bool IsGearAllowed(uint id)
		{
			HashSet<uint>? whitelistGearIds = _whitelistGearIds;
			if (whitelistGearIds == null || whitelistGearIds.Contains(id))
			{
				HashSet<uint> blacklistGearIds = _blacklistGearIds;
				if (blacklistGearIds == null)
				{
					return true;
				}
				return !blacklistGearIds.Contains(id);
			}
			return false;
		}

		private void CacheLevelLocks()
		{
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			_useOverrideProgression = false;
			_whitelistGearIds = null;
			_blacklistGearIds.Clear();
			EOSWrapper.CacheLocks(ref _whitelistGearIds, _blacklistGearIds);
			pActiveExpedition expData = RundownManager.GetActiveExpeditionData();
			uint layoutID = RundownManager.ActiveExpedition.LevelLayoutData;
			IEnumerator<LevelLockData> enumerator = LevelLockManager.Current.GetEnumerator();
			while (enumerator.MoveNext())
			{
				LevelLockData current = enumerator.Current;
				if ((current.RundownIDs.Length != 0 && !current.RundownIDs.Contains(ProgressionWrapper.CurrentRundownID)) || !current.Levels.Any((LevelTarget level) => level.IsMatch(layoutID, expData.tier, expData.expeditionIndex)))
				{
					continue;
				}
				bool flag = false;
				if (!Configuration.DisableProgression)
				{
					switch (current.UnlockMode)
					{
					case LevelUnlockMode.PerLevel:
					{
						ProgressionRequirement obj = ((current.LevelsToUnlock.Length != 0) ? current.LevelsToUnlock[0] : new ProgressionRequirement());
						obj.Tier = expData.tier;
						obj.TierIndex = expData.expeditionIndex;
						flag = IsComplete(obj, current.UnlockMissingLevelDefault);
						break;
					}
					case LevelUnlockMode.List:
						flag = IsComplete(current.LevelsToUnlock, current.UnlockRequired, current.UnlockMissingLevelDefault);
						break;
					}
				}
				else
				{
					flag = current.UnlockMode != LevelUnlockMode.None;
				}
				HashSet<uint> hashSet = (flag ? current.UnlockWhitelistIDs : current.WhitelistIDs);
				HashSet<uint> hashSet2 = (flag ? current.UnlockBlacklistIDs : current.BlacklistIDs);
				if (hashSet != null)
				{
					if (_whitelistGearIds == null)
					{
						_whitelistGearIds = new HashSet<uint>();
					}
					_whitelistGearIds.EnsureCapacity(hashSet.Count + _whitelistGearIds.Count);
					_whitelistGearIds.UnionWith(hashSet);
				}
				if (hashSet2 != null)
				{
					_blacklistGearIds.EnsureCapacity(hashSet2.Count + _blacklistGearIds.Count);
					_blacklistGearIds.UnionWith(hashSet2);
				}
				if (current.BypassProgression)
				{
					_useOverrideProgression = true;
					_overrideProgressionIds = current.WhitelistIDs;
				}
				break;
			}
		}

		private void AddGearForCurrentRundown()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected I4, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			foreach (var gearSlot in GearSlots)
			{
				InventorySlot item = gearSlot.inventorySlot;
				Dictionary<uint, GearIDRange> item2 = gearSlot.loadedGears;
				List<GearIDRange> val = ((Il2CppArrayBase<List<GearIDRange>>)(object)VanillaGearManager.m_gearPerSlot)[(int)item];
				val.Clear();
				if (item2.Count == 0)
				{
					DinoLogger.Debug($"No gear has been loaded for {item}.");
					continue;
				}
				foreach (uint key in item2.Keys)
				{
					if (!IsGearAllowed(key))
					{
						GearToggleManager.Current.RemoveFromToggleInfos(key);
					}
					else
					{
						val.Add(item2[key]);
					}
				}
				if (val.Count == 0)
				{
					DinoLogger.Warning($"No gear is allowed for {item}!");
				}
			}
		}

		private unsafe void ResetPlayerSelectedGears()
		{
			//IL_00c5: Expected O, but got Unknown
			//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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected I4, but got Unknown
			VanillaGearManager.RescanFavorites();
			foreach (var gearSlot in GearSlots)
			{
				InventorySlot item = gearSlot.inventorySlot;
				int num = (int)item;
				try
				{
					if (((Il2CppArrayBase<GearIDRange>)(object)VanillaGearManager.m_lastEquippedGearPerSlot)[num] != null)
					{
						PlayerBackpackManager.EquipLocalGear(((Il2CppArrayBase<GearIDRange>)(object)VanillaGearManager.m_lastEquippedGearPerSlot)[num]);
					}
					else if (((Il2CppArrayBase<List<GearIDRange>>)(object)VanillaGearManager.m_favoriteGearPerSlot)[num].Count > 0)
					{
						PlayerBackpackManager.EquipLocalGear(((Il2CppArrayBase<List<GearIDRange>>)(object)VanillaGearManager.m_favoriteGearPerSlot)[num][0]);
					}
					else if (((Il2CppArrayBase<List<GearIDRange>>)(object)VanillaGearManager.m_gearPerSlot)[num].Count > 0)
					{
						PlayerBackpackManager.EquipLocalGear(((Il2CppArrayBase<List<GearIDRange>>)(object)VanillaGearManager.m_gearPerSlot)[num][0]);
					}
				}
				catch (Il2CppException ex)
				{
					Il2CppException ex2 = ex;
					DinoLogger.Error("Error attempting to equip gear for slot " + ((object)(*(InventorySlot*)(&item))/*cast due to .constrained prefix*/).ToString() + ":\n" + ((Exception)(object)ex2).StackTrace);
				}
			}
		}

		private void RemoveToggleGears()
		{
			//IL_0015: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected I4, but got Unknown
			foreach (var gearSlot in GearSlots)
			{
				InventorySlot item = gearSlot.inventorySlot;
				List<GearIDRange> val = ((Il2CppArrayBase<List<GearIDRange>>)(object)VanillaGearManager.m_gearPerSlot)[(int)item];
				for (int num = val.Count - 1; num >= 0; num--)
				{
					if (!GearToggleManager.Current.IsVisibleID(val[num].GetOfflineID()))
					{
						val.RemoveAt(num);
					}
				}
			}
		}

		internal void SetupAllowedGearsForActiveRundown()
		{
			if (ProgressionWrapper.UpdateReferences())
			{
				CacheLevelLocks();
				ApplyProgressionLocks();
				AddGearForCurrentRundown();
				ResetPlayerSelectedGears();
				RemoveToggleGears();
			}
		}

		private static bool IsGearLocked(ProgressionLockData data)
		{
			if (!data.Unlock.Any() || IsComplete(data.Unlock, data.UnlockRequired, data.MissingLevelDefault))
			{
				if (data.Lock.Any())
				{
					return IsComplete(data.Lock, data.LockRequired, data.MissingLevelDefault);
				}
				return false;
			}
			return true;
		}

		private static bool IsLockExplicit(ProgressionLockData data)
		{
			if (!IsComplete(data.Unlock, data.UnlockRequired, data.MissingLevelDefault))
			{
				if (data.Lock.Any())
				{
					return IsComplete(data.Lock, data.LockRequired, data.MissingLevelDefault);
				}
				return false;
			}
			return true;
		}

		private static bool IsComplete(IEnumerable<ProgressionRequirement> list, int require, bool valueIfNone)
		{
			if (require == 0)
			{
				foreach (ProgressionRequirement item in list)
				{
					if (!IsComplete(item, valueIfNone))
					{
						return false;
					}
				}
			}
			else
			{
				foreach (ProgressionRequirement item2 in list)
				{
					if (IsComplete(item2, valueIfNone))
					{
						require--;
					}
					if (require == 0)
					{
						break;
					}
				}
			}
			return require == 0;
		}

		private static bool IsComplete(ProgressionRequirement req, bool valueIfNone)
		{
			return ProgressionWrapper.IsComplete(req, valueIfNone);
		}
	}
	public sealed class ProgressionData
	{
		public string ExpeditionKey { get; set; } = string.Empty;

		public int MainCompletionCount { get; set; }

		public int SecondaryCompletionCount { get; set; }

		public int ThirdCompletionCount { get; set; }

		public int AllCompletionCount { get; set; }

		public int NoBoosterAllClearCount { get; set; }

		public ProgressionData()
		{
		}

		public ProgressionData(string key, int main, int secondary, int third, int all, int noBooster)
		{
			ExpeditionKey = key;
			MainCompletionCount = main;
			SecondaryCompletionCount = secondary;
			ThirdCompletionCount = third;
			AllCompletionCount = all;
			NoBoosterAllClearCount = noBooster;
		}
	}
	public sealed class ProgressionLockData
	{
		public static readonly ProgressionLockData[] Template = new ProgressionLockData[2]
		{
			new ProgressionLockData
			{
				Unlock = new ProgressionRequirement[4]
				{
					new ProgressionRequirement
					{
						LevelLayoutID = 420u
					},
					new ProgressionRequirement
					{
						Tier = (eRundownTier)2
					},
					new ProgressionRequirement
					{
						LevelLayoutID = 10u,
						Main = true,
						Secondary = true
					},
					new ProgressionRequirement
					{
						Tier = (eRundownTier)1,
						TierIndex = 1,
						Main = false,
						All = true
					}
				},
				UnlockRequired = 2,
				Lock = new ProgressionRequirement[1]
				{
					new ProgressionRequirement
					{
						Tier = (eRundownTier)3
					}
				},
				LockRequired = 0,
				OfflineIDs = new List<uint> { 0u },
				Priority = 0,
				Name = "Example"
			},
			new ProgressionLockData
			{
				Name = "Empty Example"
			}
		};

		public int UnlockRequired;

		public int LockRequired;

		[JsonConverter(typeof(OptionalArrayConverter<ProgressionRequirement>))]
		public ProgressionRequirement[] Unlock { get; set; } = Array.Empty<ProgressionRequirement>();

		[JsonConverter(typeof(OptionalArrayConverter<ProgressionRequirement>))]
		public ProgressionRequirement[] Lock { get; set; } = Array.Empty<ProgressionRequirement>();

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

		public List<uint> OfflineIDs { get; set; } = new List<uint>();

		public int Priority { get; set; }

		[JsonConverter(typeof(OptionalArrayConverter<uint>))]
		public uint[] RundownIDs { get; set; } = Array.Empty<uint>();

		public string Name { get; set; } = string.Empty;
	}
	public sealed class ProgressionLockManager
	{
		public static readonly ProgressionLockManager Current = new ProgressionLockManager();

		private readonly Dictionary<string, List<ProgressionLockData>> _fileToData = new Dictionary<string, List<ProgressionLockData>>();

		private void FileChanged(FileEventArgs e)
		{
			DinoLogger.Warning("File Changed: " + e.FullPath);
			ReadFileContent(e.FullPath, e.ReadContent((Encoding)null));
		}

		private void FileDeleted(FileEventArgs e)
		{
			DinoLogger.Warning("File Removed: " + e.FullPath);
			_fileToData.Remove(e.FullPath);
			RefreshLocks();
		}

		private void FileCreated(FileEventArgs e)
		{
			DinoLogger.Warning("File Created: " + e.FullPath);
			ReadFileContent(e.FullPath, e.ReadContent((Encoding)null));
		}

		private void FileRenamed(FileRenamedEventArgs e)
		{
			DinoLogger.Warning("File Renamed: " + e.OldFileName + " -> " + ((FileEventArgs)e).FileName);
			if (_fileToData.TryGetValue(e.OldFullPath, out List<ProgressionLockData> value))
			{
				_fileToData.Remove(e.OldFullPath);
				_fileToData[((FileEventArgs)e).FullPath] = value;
			}
		}

		private void ReadFileContent(string file, string content)
		{
			_fileToData.Remove(file);
			List<ProgressionLockData> list = null;
			try
			{
				list = PWJson.Deserialize<List<ProgressionLockData>>(content);
			}
			catch (JsonException ex)
			{
				DinoLogger.Error("Error parsing progression lock json " + file);
				DinoLogger.Error(ex.Message);
			}
			if (list != null)
			{
				_fileToData[file] = list;
				RefreshLocks();
			}
		}

		private static void RefreshLocks()
		{
			GearLockManager.Current.SetupAllowedGearsForActiveRundown();
		}

		private ProgressionLockManager()
		{
			string text = Path.Combine(MTFOWrapper.CustomPath, "ProgressionGear", "ProgressionLocks");
			if (!Directory.Exists(text))
			{
				DinoLogger.Log("No ProgressionLocks directory detected. Creating template.");
				Directory.CreateDirectory(text);
				StreamWriter streamWriter = File.CreateText(Path.Combine(text, "Template.json"));
				streamWriter.WriteLine(PWJson.Serialize(ProgressionLockData.Template));
				streamWriter.Flush();
				streamWriter.Close();
			}
			else
			{
				DinoLogger.Log("ProgressionLocks directory detected.");
			}
			foreach (string item in Directory.EnumerateFiles(text, "*.json", SearchOption.AllDirectories))
			{
				string content = File.ReadAllText(item);
				ReadFileContent(item, content);
			}
			SafeFileSystemWatcher obj = SafeFileSystemWatcher.Create(text, new string[1] { "*.json" }, true);
			obj.OnCreated += FileCreated;
			obj.OnChanged += FileChanged;
			obj.OnDeleted += FileDeleted;
			obj.OnRenamed += FileRenamed;
		}

		internal void Init()
		{
		}

		public List<ProgressionLockData> GetLockData()
		{
			List<ProgressionLockData> list = new List<ProgressionLockData>(_fileToData.Values.Sum((List<ProgressionLockData> list2) => list2.Count));
			IEnumerator<ProgressionLockData> enumerator = GetEnumerator();
			while (enumerator.MoveNext())
			{
				list.Add(enumerator.Current);
			}
			return list;
		}

		public IEnumerator<ProgressionLockData> GetEnumerator()
		{
			return new DictListEnumerator<ProgressionLockData>(_fileToData);
		}
	}
	public sealed class ProgressionRequirement
	{
		public eRundownTier Tier { get; set; } = (eRundownTier)99;

		public int TierIndex { get; set; } = -1;

		public uint LevelLayoutID { get; set; }

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

		public bool Secondary { get; set; }

		public bool Overload { get; set; }

		public bool All { get; set; }

		public bool AllNoBooster { get; set; }

		public bool Complete(ProgressionData data)
		{
			if ((!AllNoBooster || data.NoBoosterAllClearCount > 0) && (!All || data.AllCompletionCount > 0) && (!Main || data.MainCompletionCount > 0) && (!Secondary || data.SecondaryCompletionCount > 0))
			{
				if (Overload)
				{
					return data.ThirdCompletionCount > 0;
				}
				return true;
			}
			return false;
		}
	}
	public static class ProgressionWrapper
	{
		private struct ExpeditionKey
		{
			public eRundownTier tier;

			public int expIndex;
		}

		private static readonly Dictionary<uint, ExpeditionKey> _layoutToExpedition;

		private static readonly Dictionary<eRundownTier, List<ExpeditionKey>> _tierExpeditionKeys;

		private static readonly Dictionary<eRundownTier, List<ProgressionData>> _nativeProgression;

		public static uint CurrentRundownID { get; private set; }

		static ProgressionWrapper()
		{
			_layoutToExpedition = new Dictionary<uint, ExpeditionKey>();
			_tierExpeditionKeys = new Dictionary<eRundownTier, List<ExpeditionKey>>
			{
				{
					(eRundownTier)1,
					new List<ExpeditionKey>()
				},
				{
					(eRundownTier)2,
					new List<ExpeditionKey>()
				},
				{
					(eRundownTier)3,
					new List<ExpeditionKey>()
				},
				{
					(eRundownTier)4,
					new List<ExpeditionKey>()
				},
				{
					(eRundownTier)5,
					new List<ExpeditionKey>()
				}
			};
			_nativeProgression = new Dictionary<eRundownTier, List<ProgressionData>>();
			CurrentRundownID = 0u;
			MTFOHotReloadAPI.OnHotReload += CacheLevelLayouts;
		}

		private static uint ActiveRundownID()
		{
			string activeRundownKey = RundownManager.ActiveRundownKey;
			uint result = default(uint);
			if (!RundownManager.RundownProgressionReady || !RundownManager.TryGetIdFromLocalRundownKey(activeRundownKey, ref result))
			{
				return 0u;
			}
			return result;
		}

		internal static void CacheLevelLayouts()
		{
			_layoutToExpedition.Clear();
			foreach (RundownDataBlock allBlock in GameDataBlockBase<RundownDataBlock>.GetAllBlocks())
			{
				AddLevelLayouts((eRundownTier)1, allBlock.TierA);
				AddLevelLayouts((eRundownTier)2, allBlock.TierB);
				AddLevelLayouts((eRundownTier)3, allBlock.TierC);
				AddLevelLayouts((eRundownTier)4, allBlock.TierD);
				AddLevelLayouts((eRundownTier)5, allBlock.TierE);
			}
		}

		public static bool UpdateReferences()
		{
			uint num = ActiveRundownID();
			if (num == 0)
			{
				return false;
			}
			if (CurrentRundownID == num)
			{
				return true;
			}
			CurrentRundownID = num;
			RundownDataBlock block = GameDataBlockBase<RundownDataBlock>.GetBlock(CurrentRundownID);
			AddTierIndices((eRundownTier)1, block.TierA);
			AddTierIndices((eRundownTier)2, block.TierB);
			AddTierIndices((eRundownTier)3, block.TierC);
			AddTierIndices((eRundownTier)4, block.TierD);
			AddTierIndices((eRundownTier)5, block.TierE);
			return true;
		}

		internal static void UpdateNativeProgression(eRundownTier tier, int expIndex, ProgressionData data)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			UpdateReferences();
			if (!_nativeProgression.ContainsKey(tier))
			{
				_nativeProgression[tier] = new List<ProgressionData>(5);
			}
			List<ProgressionData> list = _nativeProgression[tier];
			if (list.Count <= expIndex)
			{
				list.EnsureCapacity(expIndex + 1);
				for (int i = list.Count; i <= expIndex; i++)
				{
					list.Add(new ProgressionData());
				}
			}
			list[expIndex] = data;
		}

		private static void AddLevelLayouts(eRundownTier tier, List<ExpeditionInTierData> dataList)
		{
			//IL_001e: 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)
			for (int i = 0; i < dataList.Count; i++)
			{
				ExpeditionInTierData val = dataList[i];
				if (val.Enabled)
				{
					ExpeditionKey value = new ExpeditionKey
					{
						tier = tier,
						expIndex = i
					};
					_layoutToExpedition.TryAdd(val.LevelLayoutData, value);
				}
			}
		}

		private static void AddTierIndices(eRundownTier tier, List<ExpeditionInTierData> dataList)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			_tierExpeditionKeys[tier].Clear();
			for (int i = 0; i < dataList.Count; i++)
			{
				if (dataList[i].Enabled)
				{
					ExpeditionKey item = new ExpeditionKey
					{
						tier = tier,
						expIndex = i
					};
					_tierExpeditionKeys[tier].Add(item);
				}
			}
		}

		private static ProgressionData GetProgressionData(uint id, eRundownTier tier, int index)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (LocalProgressionWrapper.HasLocalProgression)
			{
				return LocalProgressionWrapper.GetProgressionDataLP(id, tier, index);
			}
			if (_nativeProgression.Count == 0)
			{
				return new ProgressionData();
			}
			return _nativeProgression[tier][index];
		}

		public static bool IsComplete(ProgressionRequirement req, bool valueIfNone = true)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			UpdateReferences();
			if (req.LevelLayoutID != 0)
			{
				if (!_layoutToExpedition.ContainsKey(req.LevelLayoutID))
				{
					return valueIfNone;
				}
				ExpeditionKey expeditionKey = _layoutToExpedition[req.LevelLayoutID];
				return req.Complete(GetProgressionData(CurrentRundownID, expeditionKey.tier, expeditionKey.expIndex));
			}
			if ((int)req.Tier != 99)
			{
				if (!_tierExpeditionKeys.ContainsKey(req.Tier))
				{
					return valueIfNone;
				}
				if (req.TierIndex >= 0)
				{
					if (req.TierIndex < _tierExpeditionKeys[req.Tier].Count)
					{
						return req.Complete(GetProgressionData(CurrentRundownID, req.Tier, req.TierIndex));
					}
					return valueIfNone;
				}
				foreach (ExpeditionKey item in _tierExpeditionKeys[req.Tier])
				{
					if (!req.Complete(GetProgressionData(CurrentRundownID, item.tier, item.expIndex)))
					{
						return false;
					}
				}
			}
			return true;
		}
	}
}
namespace ProgressionGear.Patches
{
	[HarmonyPatch]
	internal static class GearManagerPatches
	{
		private static readonly Dictionary<uint, GearIDRange> _checksumToRanges = new Dictionary<uint, GearIDRange>();

		[HarmonyPatch(typeof(GearManager), "SetupGearInOfflineMode")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Post_SetupGearInOfflineMode()
		{
			//IL_0029: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected I4, but got Unknown
			GearLockManager.Current.VanillaGearManager = GearManager.Current;
			foreach (var gearSlot in GearLockManager.Current.GearSlots)
			{
				InventorySlot item = gearSlot.inventorySlot;
				Dictionary<uint, GearIDRange> item2 = gearSlot.loadedGears;
				Enumerator<GearIDRange> enumerator2 = ((Il2CppArrayBase<List<GearIDRange>>)(object)GearManager.Current.m_gearPerSlot)[(int)item].GetEnumerator();
				while (enumerator2.MoveNext())
				{
					GearIDRange current2 = enumerator2.Current;
					uint offlineID = current2.GetOfflineID();
					item2.TryAdd(offlineID, current2);
				}
			}
			GearToggleManager.Current.ResetToggleInfos();
		}

		[HarmonyPatch(typeof(CM_PlayerInventory), "UpdateInventory")]
		[HarmonyWrapSafe]
		[HarmonyPrefix]
		private static void Pre_UpdateInventoryIcons()
		{
			_checksumToRanges.Clear();
			CacheSlot((InventorySlot)1);
			CacheSlot((InventorySlot)2);
			CacheSlot((InventorySlot)10);
			CacheSlot((InventorySlot)3);
			static void CacheSlot(InventorySlot slot)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				foreach (GearIDRange item in (Il2CppArrayBase<GearIDRange>)(object)GearManager.GetAllGearForSlot(slot))
				{
					_checksumToRanges.TryAdd(item.GetChecksum(), item);
				}
			}
		}

		[HarmonyPatch(typeof(GearManager), "CheckGearIconTargetCallbacks")]
		[HarmonyWrapSafe]
		[HarmonyPrefix]
		private static bool Pre_IconsLoadedCallbacks(uint gearKey)
		{
			if (_checksumToRanges.TryGetValue(gearKey, out GearIDRange value))
			{
				return value != null;
			}
			return true;
		}
	}
	internal static class PageRundownPatches_NoLP
	{
		[HarmonyPatch(typeof(CM_PageRundown_New), "SetIconStatus")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Post_IconUpdate(CM_ExpeditionIcon_New icon, string mainFinishCount, string secondFinishCount, string thirdFinishCount, string allFinishedCount)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			ProgressionData progressionData = new ProgressionData();
			if (mainFinishCount != "-")
			{
				progressionData.MainCompletionCount = int.Parse(mainFinishCount);
			}
			if (secondFinishCount != "-")
			{
				progressionData.SecondaryCompletionCount = int.Parse(secondFinishCount);
			}
			if (thirdFinishCount != "-")
			{
				progressionData.ThirdCompletionCount = int.Parse(thirdFinishCount);
			}
			if (allFinishedCount != "-")
			{
				progressionData.AllCompletionCount = int.Parse(allFinishedCount);
			}
			ProgressionWrapper.UpdateNativeProgression(icon.Tier, icon.ExpIndex, progressionData);
		}
	}
	[HarmonyPatch]
	internal static class PlayerLobbyBarPatches
	{
		private struct ButtonInfo
		{
			public GameObject go;

			public CM_ScrollWindowHeader item;

			public BoxCollider2D collider;

			public TextMeshPro text;

			public readonly void SetMode(bool isDouble)
			{
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: 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)
				if (isDouble)
				{
					go.transform.localPosition = DoubleButtonPos;
					((Collider2D)collider).offset = Vector2.op_Implicit(DoubleColliderOffset);
				}
				else
				{
					go.transform.localPosition = SingleButtonPos;
					((Collider2D)collider).offset = Vector2.op_Implicit(SingleColliderOffset);
				}
			}
		}

		private static readonly Vector3 SingleButtonPos = new Vector3(360f, -800f, -2f);

		private static readonly Vector3 DoubleButtonPos = new Vector3(500f, -800f, -2f);

		private static readonly Vector3 SingleColliderOffset = new Vector3(90f, -6.5f);

		private static readonly Vector3 DoubleColliderOffset = new Vector3(100f, -6.5f);

		private static CM_InventorySlotItem? _cachedItem;

		private static ButtonInfo _leftButton;

		private static ButtonInfo _rightButton;

		private static CM_PlayerLobbyBar? _activeBar;

		[HarmonyPatch(typeof(CM_PlayerLobbyBar), "ShowWeaponSelectionPopup")]
		[HarmonyAfter(new string[] { "Inas.ExtraObjectiveSetup", "Amor.ExcellentObjectiveSetup" })]
		[HarmonyWrapSafe]
		[HarmonyPrefix]
		private static void Pre_ShowLoadoutForSlot()
		{
			uint currentRundownID = ProgressionWrapper.CurrentRundownID;
			if (ProgressionWrapper.UpdateReferences() && currentRundownID != ProgressionWrapper.CurrentRundownID)
			{
				GearLockManager.Current.SetupAllowedGearsForActiveRundown();
			}
		}

		[HarmonyPatch(typeof(CM_PlayerLobbyBar), "UpdateWeaponWindowInfo")]
		[HarmonyPrefix]
		private static void Pre_LoadoutHeaderSelected(CM_PlayerLobbyBar __instance)
		{
			_cachedItem = __instance.selectedWeaponSlotItem;
		}

		[HarmonyPatch(typeof(CM_PlayerLobbyBar), "UpdateWeaponWindowInfo")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Post_LoadoutHeaderSelected(CM_PlayerLobbyBar __instance, InventorySlot slot)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			BackpackItem val = default(BackpackItem);
			if ((Object)(object)_cachedItem != (Object)(object)__instance.selectedWeaponSlotItem || !PlayerBackpackManager.TryGetItem(__instance.m_player, slot, ref val) || val.GearIDRange == null)
			{
				return;
			}
			uint offlineID = val.GearIDRange.GetOfflineID();
			if (!GearToggleManager.Current.TryGetToggleInfo(offlineID, out var toggleInfo))
			{
				return;
			}
			foreach (iScrollWindowContent item in (Il2CppArrayBase<iScrollWindowContent>)(object)__instance.m_popupScrollWindow.ContentItems)
			{
				CM_InventorySlotItem val2 = ((Il2CppObjectBase)item).TryCast<CM_InventorySlotItem>();
				if (toggleInfo.ids.Contains(val2.m_gearID.GetOfflineID()))
				{
					val2.IsPicked = true;
					val2.LoadData(val.GearIDRange, true, true);
					__instance.OnWeaponSlotItemSelected(val2);
					_cachedItem = __instance.selectedWeaponSlotItem;
					break;
				}
			}
		}

		[HarmonyPatch(typeof(CM_ScrollWindow), "Setup", new Type[] { })]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Post_LobbyBarSetup(CM_ScrollWindow __instance)
		{
			if (!((Object)(object)_rightButton.go != (Object)null))
			{
				CreateButton(__instance, ref _rightButton, right: true);
				CreateButton(__instance, ref _leftButton, right: false);
			}
		}

		[HarmonyPatch(typeof(CM_ScrollWindow), "ResetHeaders")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Post_ResetHeaders()
		{
			if (!((Object)(object)_rightButton.go == (Object)null))
			{
				_rightButton.go.SetActive(false);
				_leftButton.go.SetActive(false);
			}
		}

		[HarmonyPatch(typeof(CM_PlayerLobbyBar), "ShowWeaponSelectionPopup")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Post_LoadoutMenuOpened(CM_PlayerLobbyBar __instance)
		{
			//IL_004c: 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)
			CM_ScrollWindow popupScrollWindow = __instance.m_popupScrollWindow;
			_rightButton.go.transform.SetParent(((Component)popupScrollWindow).transform, false);
			_leftButton.go.transform.SetParent(((Component)popupScrollWindow).transform, false);
			_rightButton.go.transform.localPosition = DoubleButtonPos;
			_leftButton.go.transform.localPosition = DoubleButtonPos;
			popupScrollWindow.AddNonContentItem((CM_Item)(object)_rightButton.item);
			popupScrollWindow.AddNonContentItem((CM_Item)(object)_leftButton.item);
			_activeBar = __instance;
			if ((Object)(object)__instance.selectedWeaponSlotItem != (Object)null)
			{
				Post_LoadoutItemSelected(__instance.selectedWeaponSlotItem);
			}
		}

		[HarmonyPatch(typeof(CM_PlayerLobbyBar), "OnWeaponSlotItemSelected")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Post_LoadoutItemSelected(CM_InventorySlotItem slotItem)
		{
			if ((Object)(object)_rightButton.go == (Object)null)
			{
				return;
			}
			uint offlineID = slotItem.m_gearID.GetOfflineID();
			if (GearToggleManager.Current.TryGetToggleInfo(offlineID, out var toggleInfo))
			{
				if (toggleInfo.text.Length > 1)
				{
					_rightButton.go.SetActive(true);
					_rightButton.SetMode(isDouble: true);
					((TMP_Text)_rightButton.text).SetText(LocalizedText.op_Implicit(toggleInfo.text[0]), true);
					_leftButton.go.SetActive(true);
					((TMP_Text)_leftButton.text).SetText(LocalizedText.op_Implicit(toggleInfo.text[1]), true);
				}
				else
				{
					_rightButton.go.SetActive(true);
					_rightButton.SetMode(isDouble: false);
					((TMP_Text)_rightButton.text).SetText(LocalizedText.op_Implicit(toggleInfo.text[0]), true);
					_leftButton.go.SetActive(false);
				}
			}
			else
			{
				_rightButton.go.SetActive(false);
				_leftButton.go.SetActive(false);
			}
		}

		private static void CreateButton(CM_ScrollWindow window, ref ButtonInfo button, bool right)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			button.go = Object.Instantiate<GameObject>(((Component)((Il2CppArrayBase<CM_ScrollWindowHeader>)(object)window.m_headers)[0]).gameObject);
			((Object)button.go).name = "PG_" + (right ? "Right" : "Left");
			CM_ScrollWindowHeader val = (button.item = button.go.GetComponent<CM_ScrollWindowHeader>());
			val.SetSelected(false);
			Transform transform = button.go.transform;
			transform.localScale = Vector3.one * 1.5f;
			transform.Rotate(0f, (float)(right ? 180 : 0), 180f);
			Transform child = transform.GetChild(0);
			child.localPosition = new Vector3(5f, -25f, 0f);
			((Component)child).GetComponent<SpriteRenderer>().size = new Vector2(2600f, 29f);
			Transform child2 = transform.GetChild(1);
			child2.Rotate(0f, (float)(right ? 180 : 0), 180f);
			child2.localPosition = (right ? new Vector3(-10f, -5f, 0f) : new Vector3(185f, -5f, 0f));
			button.text = ((Il2CppArrayBase<TextMeshPro>)(object)((CM_Item)val).m_texts)[0];
			((TMP_Text)button.text).alignment = (TextAlignmentOptions)4098;
			transform.GetChild(2).localScale = new Vector3(0.8f, 1f, 1f);
			button.collider = ((CM_Item)val).m_collider;
			button.collider.size = new Vector2(200f, 40f);
			((Collider2D)button.collider).offset = Vector2.op_Implicit(DoubleColliderOffset);
			button.go.SetActive(false);
			((CM_Item)val).OnBtnPressCallback = null;
			((CM_Item)val).OnBtnPressCallback += Action<int>.op_Implicit(ButtonPressedCallback(right));
		}

		private static Action<int> ButtonPressedCallback(bool toNext)
		{
			return delegate
			{
				CM_InventorySlotItem val = _activeBar.selectedWeaponSlotItem ?? _cachedItem;
				if (!((Object)(object)val == (Object)null))
				{
					uint offlineID = val.m_gearID.GetOfflineID();
					ToggleInfo toggleInfo = GearToggleManager.Current.GetToggleInfo(offlineID);
					List<uint> ids = toggleInfo.ids;
					int num = ((toNext ^ toggleInfo.reverse) ? 1 : (ids.Count - 1));
					uint value = ids[(ids.IndexOf(offlineID) + num) % ids.Count];
					GearIDRange val2 = default(GearIDRange);
					if (GearManager.TryGetGear("OfflineGear_ID_" + value, ref val2))
					{
						val.LoadData(val2, true, true);
						_activeBar.OnWeaponSlotItemSelected(val);
					}
					else
					{
						DinoLogger.Error($"Couldn't swap to next weapon ({value}) in toggle list!");
					}
				}
			};
		}
	}
	[HarmonyPatch]
	internal static class RundownManagerPatches
	{
		[HarmonyPatch(typeof(RundownManager), "SetActiveExpedition")]
		[HarmonyAfter(new string[] { "Inas.ExtraObjectiveSetup", "Amor.ExcellentObjectiveSetup" })]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		private static void Post_RundownManager_SetActiveExpedition(pActiveExpedition expPackage)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)expPackage.tier != 99)
			{
				GearLockManager.Current.SetupAllowedGearsForActiveRundown();
			}
		}
	}
}
namespace ProgressionGear.LevelLock
{
	public sealed class LevelLockData
	{
		public static readonly LevelLockData[] Template = new LevelLockData[3]
		{
			new LevelLockData
			{
				Levels = new LevelTarget[1]
				{
					new LevelTarget
					{
						LevelLayoutID = 420u
					}
				},
				Name = "Level Layout ID"
			},
			new LevelLockData
			{
				Levels = new LevelTarget[1]
				{
					new LevelTarget
					{
						Tier = (eRundownTier)1,
						TierIndex = 0
					}
				},
				LevelsToUnlock = new ProgressionRequirement[2]
				{
					new ProgressionRequirement
					{
						Tier = (eRundownTier)1,
						TierIndex = 1
					},
					new ProgressionRequirement
					{
						Tier = (eRundownTier)1,
						TierIndex = 2
					}
				},
				UnlockMode = LevelUnlockMode.List,
				Name = "TierIndex example"
			},
			new LevelLockData
			{
				Levels = new LevelTarget[2]
				{
					new LevelTarget
					{
						LevelLayoutID = 420u
					},
					new LevelTarget
					{
						Tier = (eRundownTier)1,
						TierIndex = 0
					}
				},
				UnlockMode = LevelUnlockMode.PerLevel,
				BlacklistIDs = new HashSet<uint> { 0u },
				Name = "List example"
			}
		};

		[JsonConverter(typeof(OptionalArrayConverter<LevelTarget>))]
		public LevelTarget[] Levels { get; set; } = Array.Empty<LevelTarget>();

		public HashSet<uint>? WhitelistIDs { get; set; }

		public HashSet<uint>? BlacklistIDs { get; set; }

		public bool BypassProgression { get; set; }

		[JsonConverter(typeof(OptionalArrayConverter<ProgressionRequirement>))]
		public ProgressionRequirement[] LevelsToUnlock { get; set; } = Array.Empty<ProgressionRequirement>();

		public LevelUnlockMode UnlockMode { get; set; }

		public HashSet<uint>? UnlockWhitelistIDs { get; set; }

		public HashSet<uint>? UnlockBlacklistIDs { get; set; }

		public int UnlockRequired { get; set; }

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

		[JsonConverter(typeof(OptionalArrayConverter<uint>))]
		public uint[] RundownIDs { get; set; } = Array.Empty<uint>();

		public string Name { get; set; } = string.Empty;
	}
	public sealed class LevelLockManager
	{
		public static readonly LevelLockManager Current = new LevelLockManager();

		private readonly Dictionary<string, List<LevelLockData>> _fileToData = new Dictionary<string, List<LevelLockData>>();

		private void FileChanged(FileEventArgs e)
		{
			DinoLogger.Warning("File Changed: " + e.FullPath);
			ReadFileContent(e.FullPath, e.ReadContent((Encoding)null));
		}

		private void FileDeleted(FileEventArgs e)
		{
			DinoLogger.Warning("File Removed: " + e.FullPath);
			_fileToData.Remove(e.FullPath);
			RefreshLocks();
		}

		private void FileCreated(FileEventArgs e)
		{
			DinoLogger.Warning("File Created: " + e.FullPath);
			ReadFileContent(e.FullPath, e.ReadContent((Encoding)null));
		}

		private void FileRenamed(FileRenamedEventArgs e)
		{
			DinoLogger.Warning("File Renamed: " + e.OldFileName + " -> " + ((FileEventArgs)e).FileName);
			if (_fileToData.TryGetValue(e.OldFullPath, out List<LevelLockData> value))
			{
				_fileToData.Remove(e.OldFullPath);
				_fileToData[((FileEventArgs)e).FullPath] = value;
			}
		}

		private void ReadFileContent(string file, string content)
		{
			_fileToData.Remove(file);
			List<LevelLockData> list = null;
			try
			{
				list = PWJson.Deserialize<List<LevelLockData>>(content);
			}
			catch (JsonException ex)
			{
				DinoLogger.Error("Error parsing progression lock json " + file);
				DinoLogger.Error(ex.Message);
			}
			if (list != null)
			{
				_fileToData[file] = list;
				RefreshLocks();
			}
		}

		private static void RefreshLocks()
		{
			GearLockManager.Current.SetupAllowedGearsForActiveRundown();
		}

		private LevelLockManager()
		{
			string text = Path.Combine(MTFOWrapper.CustomPath, "ProgressionGear", "LevelLocks");
			if (!Directory.Exists(text))
			{
				DinoLogger.Log("No LevelLocks directory detected. Creating template.");
				Directory.CreateDirectory(text);
				StreamWriter streamWriter = File.CreateText(Path.Combine(text, "Template.json"));
				streamWriter.WriteLine(PWJson.Serialize(LevelLockData.Template));
				streamWriter.Flush();
				streamWriter.Close();
			}
			else
			{
				DinoLogger.Log("LevelLocks directory detected.");
			}
			foreach (string item in Directory.EnumerateFiles(text, "*.json", SearchOption.AllDirectories))
			{
				string content = File.ReadAllText(item);
				ReadFileContent(item, content);
			}
			SafeFileSystemWatcher obj = SafeFileSystemWatcher.Create(text, new string[1] { "*.json" }, true);
			obj.OnCreated += FileCreated;
			obj.OnChanged += FileChanged;
			obj.OnDeleted += FileDeleted;
			obj.OnRenamed += FileRenamed;
		}

		internal void Init()
		{
		}

		public List<LevelLockData> GetLockData()
		{
			List<LevelLockData> list = new List<LevelLockData>(_fileToData.Values.Sum((List<LevelLockData> list2) => list2.Count));
			IEnumerator<LevelLockData> enumerator = GetEnumerator();
			while (enumerator.MoveNext())
			{
				list.Add(enumerator.Current);
			}
			return list;
		}

		public IEnumerator<LevelLockData> GetEnumerator()
		{
			return new DictListEnumerator<LevelLockData>(_fileToData);
		}
	}
	public enum LevelUnlockMode
	{
		None,
		PerLevel,
		List
	}
}
namespace ProgressionGear.JSON
{
	[JsonConverter(typeof(LevelTargetConverter))]
	public sealed class LevelTarget
	{
		public uint LevelLayoutID { get; set; }

		public eRundownTier Tier { get; set; } = (eRundownTier)99;

		public int TierIndex { get; set; } = -1;

		public bool IsMatch(uint layoutID, eRundownTier tier, int tierIndex)
		{
			//IL_000c: 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)
			if (layoutID == LevelLayoutID)
			{
				return true;
			}
			if (Tier == tier && (TierIndex == -1 || TierIndex == tierIndex))
			{
				return true;
			}
			return false;
		}
	}
	public static class PWJson
	{
		private static readonly JsonSerializerOptions _settings;

		static PWJson()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			_settings = new JsonSerializerOptions
			{
				ReadCommentHandling = JsonCommentHandling.Skip,
				IncludeFields = true,
				PropertyNameCaseInsensitive = true,
				WriteIndented = true,
				IgnoreReadOnlyProperties = true
			};
			_settings.Converters.Add(new JsonStringEnumConverter());
			_settings.Converters.Add((JsonConverter)new LocalizedTextConverter());
			_settings.Converters.Add(new ProgressionRequirementConverter());
			_settings.Converters.Add(new ProgressionLockDataConverter());
			_settings.Converters.Add(new GearToggleDataConverter());
			if (PartialDataWrapper.HasPartialData)
			{
				_settings.Converters.Add(PartialDataWrapper.PersistentIDConverter);
			}
		}

		public static T? Deserialize<T>(string json)
		{
			return JsonSerializer.Deserialize<T>(json, _settings);
		}

		public static object? Deserialize(Type type, string json)
		{
			return JsonSerializer.Deserialize(json, type, _settings);
		}

		public static T? Deserialize<T>(ref Utf8JsonReader reader)
		{
			return JsonSerializer.Deserialize<T>(ref reader, _settings);
		}

		public static bool TryDeserialize<T>(ref Utf8JsonReader reader, [MaybeNullWhen(false)] out T value)
		{
			value = Deserialize<T>(ref reader);
			return value != null;
		}

		public static bool TryDeserialize<T>(ref Utf8JsonReader reader, [MaybeNullWhen(false)] out T value, JsonSerializerOptions options)
		{
			value = JsonSerializer.Deserialize<T>(ref reader, options);
			return value != null;
		}

		public static string Serialize<T>(T value)
		{
			return JsonSerializer.Serialize(value, _settings);
		}

		public static void Serialize<T>(Utf8JsonWriter writer, T value)
		{
			JsonSerializer.Serialize(writer, value, _settings);
		}

		public static void Serialize<T>(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
		{
			JsonSerializer.Serialize(writer, value, options);
		}

		public static void Serialize<T>(Utf8JsonWriter writer, string name, T value, JsonSerializerOptions options)
		{
			writer.WritePropertyName(name);
			JsonSerializer.Serialize(writer, value, options);
		}
	}
}
namespace ProgressionGear.JSON.Converters
{
	public sealed class GearToggleDataConverter : JsonConverter<GearToggleData>
	{
		public override GearToggleData? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			GearToggleData gearToggleData = new GearToggleData();
			if (reader.TokenType != JsonTokenType.StartObject)
			{
				throw new JsonException("Expected progression lock to be an object");
			}
			while (reader.Read())
			{
				if (reader.TokenType == JsonTokenType.EndObject)
				{
					return gearToggleData;
				}
				if (reader.TokenType != JsonTokenType.PropertyName)
				{
					throw new JsonException("Expected PropertyName token");
				}
				string? text = reader.GetString();
				reader.Read();
				switch (text.ToLowerInvariant().Replace(" ", ""))
				{
				case "offlineids":
				{
					if (PWJson.TryDeserialize<List<uint>>(ref reader, out var value, options))
					{
						gearToggleData.OfflineIDs = value;
						break;
					}
					throw new JsonException("GearToggle: Failed to read OfflineIDs!");
				}
				case "buttontext":
				{
					if (TryReadButtonText(ref reader, out LocalizedText[] buttonText, options))
					{
						gearToggleData.ButtonText = buttonText;
						break;
					}
					throw new JsonException("GearToggle: Failed to read ButtonText!");
				}
				case "reverseorder":
					if (reader.TokenType != JsonTokenType.True && reader.TokenType != JsonTokenType.False)
					{
						throw new JsonException("GearToggle: Expected boolean for ReverseOrder");
					}
					gearToggleData.ReverseOrder = reader.GetBoolean();
					break;
				case "name":
					if (reader.TokenType != JsonTokenType.String)
					{
						throw new JsonException("GearToggle: Expected string for Name");
					}
					gearToggleData.Name = reader.GetString();
					break;
				}
			}
			throw new JsonException("Expected EndObject token");
		}

		private static bool TryReadButtonText(ref Utf8JsonReader reader, out LocalizedText[] buttonText, JsonSerializerOptions options)
		{
			if (reader.TokenType == JsonTokenType.StartArray)
			{
				buttonText = (LocalizedText[])(object)new LocalizedText[2];
				reader.Read();
				if (!PWJson.TryDeserialize<LocalizedText>(ref reader, out buttonText[1], options))
				{
					throw new JsonException("GearToggle: Failed to read right ButtonText!");
				}
				reader.Read();
				if (reader.TokenType == JsonTokenType.EndArray)
				{
					buttonText = (LocalizedText[])(object)new LocalizedText[1] { buttonText[1] };
					return true;
				}
				if (reader.TokenType == JsonTokenType.Null)
				{
					buttonText = (LocalizedText[])(object)new LocalizedText[1] { buttonText[1] };
					reader.Read();
				}
				else if (!PWJson.TryDeserialize<LocalizedText>(ref reader, out buttonText[0], options))
				{
					throw new JsonException("GearToggle: Failed to read left ButtonText!");
				}
				reader.Read();
				if (reader.TokenType != JsonTokenType.EndArray)
				{
					throw new JsonException($"GearToggle: Expected EndArray token when reading ButtonText, found {reader.TokenType}");
				}
				return true;
			}
			buttonText = (LocalizedText[])(object)new LocalizedText[1];
			if (!PWJson.TryDeserialize<LocalizedText>(ref reader, out buttonText[0], options))
			{
				throw new JsonException("GearToggle: Failed to read ButtonText!");
			}
			return true;
		}

		public override void Write(Utf8JsonWriter writer, GearToggleData? value, JsonSerializerOptions options)
		{
			if (value != null)
			{
				writer.WriteStartObject();
				PWJson.Serialize(writer, "OfflineIDs", value.OfflineIDs, options);
				if (value.ButtonText.Length > 1)
				{
					writer.WriteStartArray("ButtonText");
					PWJson.Serialize<LocalizedText>(writer, value.ButtonText[0], options);
					PWJson.Serialize<LocalizedText>(writer, value.ButtonText[1], options);
					writer.WriteEndArray();
				}
				else
				{
					PWJson.Serialize<LocalizedText>(writer, "ButtonText", value.ButtonText[0], options);
				}
				writer.WriteBoolean("ReverseOrder", value.ReverseOrder);
				writer.WriteString("Name", value.Name);
				writer.WriteEndObject();
			}
		}
	}
	public sealed class LevelTargetConverter : JsonConverter<LevelTarget>
	{
		public override LevelTarget? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			LevelTarget levelTarget = new LevelTarget();
			if (ParseTarget(ref reader, levelTarget, options))
			{
				return levelTarget;
			}
			throw new JsonException("Expected level target to be a tier, tierindex, or level layout ID");
		}

		private static bool ParseTarget(ref Utf8JsonReader reader, LevelTarget target, JsonSerializerOptions options)
		{
			//IL_005b: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			if (reader.TokenType == JsonTokenType.Null)
			{
				return true;
			}
			if (reader.TokenType == JsonTokenType.String)
			{
				string text = reader.GetString();
				if (text.Length >= 5)
				{
					target.Tier = text.Substring(0, 5).ToEnum<eRundownTier>((eRundownTier)99);
				}
				else
				{
					target.Tier = ("Tier" + text[0]).ToEnum<eRundownTier>((eRundownTier)99);
				}
				int num = ((text.Length < 5) ? 1 : 5);
				if ((int)target.Tier != 99 && text.Length > num)
				{
					if (int.TryParse(text.Substring(num), out var result))
					{
						target.TierIndex = result - 1;
					}
					else
					{
						target.Tier = (eRundownTier)99;
					}
				}
				if ((int)target.Tier == 99)
				{
					target.LevelLayoutID = JsonSerializer.Deserialize<uint>(ref reader, options);
				}
				return true;
			}
			if (reader.TokenType == JsonTokenType.Number)
			{
				target.LevelLayoutID = reader.GetUInt32();
				return true;
			}
			return false;
		}

		public override void Write(Utf8JsonWriter writer, LevelTarget? value, JsonSerializerOptions options)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (value != null)
			{
				if (value.LevelLayoutID == 0 && (int)value.Tier == 99)
				{
					writer.WriteNullValue();
					return;
				}
				if (value.LevelLayoutID != 0)
				{
					writer.WriteNumberValue(value.LevelLayoutID);
					return;
				}
				string? text = ((object)value.Tier/*cast due to .constrained prefix*/).ToString();
				writer.WriteStringValue(text[text.Length - 1] + ((value.TierIndex >= 0) ? (value.TierIndex + 1).ToString() : ""));
			}
		}
	}
	public sealed class OptionalArrayConverter<T> : JsonConverter<T[]>
	{
		public override T[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			if (reader.TokenType == JsonTokenType.StartArray)
			{
				List<T> list = new List<T>();
				while (reader.Read())
				{
					if (reader.TokenType == JsonTokenType.EndArray)
					{
						return list.ToArray();
					}
					list.Add(JsonSerializer.Deserialize<T>(ref reader, options));
				}
				throw new JsonException("Expected EndArray when reading list");
			}
			return new T[1] { JsonSerializer.Deserialize<T>(ref reader, options) };
		}

		public override void Write(Utf8JsonWriter writer, T[] value, JsonSerializerOptions options)
		{
			if (value.Length == 1)
			{
				JsonSerializer.Serialize(writer, value[0], options);
				return;
			}
			writer.WriteStartArray();
			foreach (T value2 in value)
			{
				JsonSerializer.Serialize(writer, value2, options);
			}
			writer.WriteEndArray();
		}
	}
	public sealed class ProgressionLockDataConverter : JsonConverter<ProgressionLockData>
	{
		public override ProgressionLockData? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			ProgressionLockData progressionLockData = new ProgressionLockData();
			if (reader.TokenType != JsonTokenType.StartObject)
			{
				throw new JsonException("Expected progression lock to be an object");
			}
			JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(options);
			jsonSerializerOptions.Converters.Add(new OptionalArrayConverter<ProgressionRequirement>());
			jsonSerializerOptions.Converters.Add(new OptionalArrayConverter<uint>());
			while (reader.Read())
			{
				if (reader.TokenType == JsonTokenType.EndObject)
				{
					return progressionLockData;
				}
				if (reader.TokenType != JsonTokenType.PropertyName)
				{
					throw new JsonException("Expected PropertyName token");
				}
				string? text = reader.GetString();
				reader.Read();
				switch (text.ToLowerInvariant().Replace(" ", ""))
				{
				case "unlocklayoutids":
				case "unlocktiers":
				case "unlock":
				{
					if (PWJson.TryDeserialize<ProgressionRequirement[]>(ref reader, out var value3, jsonSerializerOptions))
					{
						progressionLockData.Unlock = value3;
					}
					break;
				}
				case "unlockrequired":
					if (reader.TokenType != JsonTokenType.Number)
					{
						throw new JsonException("Expected number for UnlockRequired");
					}
					progressionLockData.UnlockRequired = reader.GetInt32();
					break;
				case "locktiers":
				case "lock":
				case "locklayoutids":
				{
					if (PWJson.TryDeserialize<ProgressionRequirement[]>(ref reader, out var value2, jsonSerializerOptions))
					{
						progressionLockData.Lock = value2;
					}
					break;
				}
				case "lockrequired":
					if (reader.TokenType != JsonTokenType.Number)
					{
						throw new JsonException("Expected number for LockRequired");
					}
					progressionLockData.LockRequired = reader.GetInt32();
					break;
				case "missingleveldefault":
					if (reader.TokenType != JsonTokenType.True && reader.TokenType != JsonTokenType.False)
					{
						throw new JsonException("Expected boolean for MissingLevelDefault");
					}
					progressionLockData.MissingLevelDefault = reader.GetBoolean();
					break;
				case "offlineids":
				{
					if (PWJson.TryDeserialize<List<uint>>(ref reader, out var value4, options))
					{
						progressionLockData.OfflineIDs = value4;
					}
					break;
				}
				case "priority":
					if (reader.TokenType != JsonTokenType.Number)
					{
						throw new JsonException("Expected number for Priority");
					}
					progressionLockData.Priority = reader.GetInt32();
					break;
				case "rundownid":
				case "rundownids":
				{
					if (PWJson.TryDeserialize<uint[]>(ref reader, out var value, jsonSerializerOptions))
					{
						progressionLockData.RundownIDs = value;
					}
					break;
				}
				case "name":
					if (reader.TokenType != JsonTokenType.String)
					{
						throw new JsonException("Expected string for Name");
					}
					progressionLockData.Name = reader.GetString();
					break;
				}
			}
			throw new JsonException("Expected EndObject token");
		}

		public override void Write(Utf8JsonWriter writer, ProgressionLockData? value, JsonSerializerOptions options)
		{
			if (value != null)
			{
				writer.WriteStartObject();
				writer.WritePropertyName("Unlock");
				PWJson.Serialize(writer, value.Unlock);
				writer.WriteNumber("UnlockRequired", value.UnlockRequired);
				writer.WritePropertyName("Lock");
				PWJson.Serialize(writer, value.Lock);
				writer.WriteNumber("LockRequired", value.LockRequired);
				writer.WritePropertyName("OfflineIDs");
				PWJson.Serialize(writer, value.OfflineIDs);
				writer.WriteNumber("Priority", value.Priority);
				writer.WriteString("Name", value.Name);
				writer.WriteEndObject();
			}
		}
	}
	public sealed class ProgressionRequirementConverter : JsonConverter<ProgressionRequirement>
	{
		public override ProgressionRequirement? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			ProgressionRequirement progressionRequirement = new ProgressionRequirement();
			if (ParseRequirement(ref reader, progressionRequirement, options))
			{
				return progressionRequirement;
			}
			if (reader.TokenType != JsonTokenType.StartObject)
			{
				throw new JsonException("Expected progression requirement to be a tier, level layout ID, or object");
			}
			while (reader.Read())
			{
				if (reader.TokenType == JsonTokenType.EndObject)
				{
					return progressionRequirement;
				}
				if (reader.TokenType != JsonTokenType.PropertyName)
				{
					throw new JsonException("Expected PropertyName token");
				}
				string? text = reader.GetString();
				reader.Read();
				switch (text.ToLowerInvariant().Replace(" ", ""))
				{
				case "levellayout":
				case "requirement":
				case "levelid":
				case "tier":
				case "level":
				case "levellayoutid":
					ParseRequirement(ref reader, progressionRequirement, options);
					break;
				case "high":
				case "main":
					progressionRequirement.Main = reader.GetBoolean();
					break;
				case "extreme":
				case "secondary":
					progressionRequirement.Secondary = reader.GetBoolean();
					break;
				case "overload":
					progressionRequirement.Overload = reader.GetBoolean();
					break;
				case "all":
				case "pe":
				case "prisonerefficiency":
					progressionRequirement.All = reader.GetBoolean();
					break;
				case "penobooster":
				case "allnobooster":
				case "prisonerefficiencynobooster":
					progressionRequirement.AllNoBooster = reader.GetBoolean();
					break;
				}
			}
			throw new JsonException("Expected EndObject token");
		}

		private static bool ParseRequirement(ref Utf8JsonReader reader, ProgressionRequirement req, JsonSerializerOptions options)
		{
			//IL_005b: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			if (reader.TokenType == JsonTokenType.Null)
			{
				return true;
			}
			if (reader.TokenType == JsonTokenType.String)
			{
				string text = reader.GetString();
				if (text.Length >= 5)
				{
					req.Tier = text.Substring(0, 5).ToEnum<eRundownTier>((eRundownTier)99);
				}
				else
				{
					req.Tier = ("Tier" + text[0]).ToEnum<eRundownTier>((eRundownTier)99);
				}
				int num = ((text.Length < 5) ? 1 : 5);
				if ((int)req.Tier != 99 && text.Length > num)
				{
					if (int.TryParse(text.Substring(num), out var result))
					{
						req.TierIndex = result - 1;
					}
					else
					{
						req.Tier = (eRundownTier)99;
					}
				}
				if ((int)req.Tier == 99)
				{
					req.LevelLayoutID = JsonSerializer.Deserialize<uint>(ref reader, options);
				}
				return true;
			}
			if (reader.TokenType == JsonTokenType.Number)
			{
				req.LevelLayoutID = reader.GetUInt32();
				return true;
			}
			return false;
		}

		public override void Write(Utf8JsonWriter writer, ProgressionRequirement? value, JsonSerializerOptions options)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (value == null)
			{
				return;
			}
			if (value.LevelLayoutID == 0 && (int)value.Tier == 99)
			{
				writer.WriteNullValue();
				return;
			}
			if (value.Main && !value.Secondary && !value.Overload && !value.All)
			{
				if (value.LevelLayoutID != 0)
				{
					writer.WriteNumberValue(value.LevelLayoutID);
					return;
				}
				string? text = ((object)value.Tier/*cast due to .constrained prefix*/).ToString();
				writer.WriteStringValue(text[text.Length - 1] + ((value.TierIndex >= 0) ? (value.TierIndex + 1).ToString() : ""));
				return;
			}
			writer.WriteStartObject();
			writer.WritePropertyName("Level");
			if (value.LevelLayoutID != 0)
			{
				writer.WriteNumberValue(value.LevelLayoutID);
			}
			else
			{
				string? text2 = ((object)value.Tier/*cast due to .constrained prefix*/).ToString();
				writer.WriteStringValue(text2[text2.Length - 1] + ((value.TierIndex >= 0) ? (value.TierIndex + 1).ToString() : ""));
			}
			writer.WriteBoolean("Main", value.Main);
			writer.WriteBoolean("Secondary", value.Secondary);
			writer.WriteBoolean("Overload", value.Overload);
			writer.WriteBoolean("All", value.All);
			writer.WriteBoolean("AllNoBooster", value.AllNoBooster);
			writer.WriteEndObject();
		}
	}
}
namespace ProgressionGear.GearToggle
{
	public sealed class GearToggleData
	{
		private static readonly List<uint> DefaultIDs = new List<uint>();

		private static readonly LocalizedText DefaultText = new LocalizedText
		{
			Id = 0u,
			UntranslatedText = "Switch Gear"
		};

		private static readonly LocalizedText[] DefaultTextArr = (LocalizedText[])(object)new LocalizedText[1] { DefaultText };

		public static readonly GearToggleData[] Template = new GearToggleData[2]
		{
			new GearToggleData(),
			new GearToggleData
			{
				ButtonText = (LocalizedText[])(object)new LocalizedText[2]
				{
					new LocalizedText
					{
						Id = 0u,
						UntranslatedText = "Previous"
					},
					new LocalizedText
					{
						Id = 0u,
						UntranslatedText = "Next"
					}
				}
			}
		};

		public List<uint> OfflineIDs { get; set; } = DefaultIDs;

		[JsonConverter(typeof(OptionalArrayConverter<LocalizedText>))]
		public LocalizedText[] ButtonText { get; set; } = DefaultTextArr;

		public bool ReverseOrder { get; set; }

		public string Name { get; set; } = string.Empty;
	}
	public sealed class GearToggleManager
	{
		public static readonly GearToggleManager Current = new GearToggleManager();

		private readonly Dictionary<string, List<GearToggleData>> _fileToData = new Dictionary<string, List<GearToggleData>>();

		private readonly Dictionary<uint, ToggleInfo> _idToInfo = new Dictionary<uint, ToggleInfo>();

		private void FileChanged(FileEventArgs e)
		{
			DinoLogger.Warning("File Changed: " + e.FileName);
			ReadFileContent(e.FullPath, e.ReadContent((Encoding)null));
		}

		private void FileDeleted(FileEventArgs e)
		{
			DinoLogger.Warning("File Removed: " + e.FileName);
			_fileToData.Remove(e.FullPath);
			ResetToggleInfos();
			RefreshLocks();
		}

		private void FileCreated(FileEventArgs e)
		{
			DinoLogger.Warning("File Created: " + e.FileName);
			ReadFileContent(e.FullPath, e.ReadContent((Encoding)null));
		}

		private void FileRenamed(FileRenamedEventArgs e)
		{
			DinoLogger.Warning("File Renamed: " + e.OldFileName + " -> " + ((FileEventArgs)e).FileName);
			if (_fileToData.TryGetValue(e.OldFullPath, out List<GearToggleData> value))
			{
				_fileToData.Remove(e.OldFullPath);
				_fileToData[((FileEventArgs)e).FullPath] = value;
			}
		}

		private void ReadFileContent(string file, string content)
		{
			_fileToData.Remove(file);
			List<GearToggleData> list = null;
			try
			{
				list = PWJson.Deserialize<List<GearToggleData>>(content);
			}
			catch (JsonException ex)
			{
				DinoLogger.Error("Error parsing progression lock json " + file);
				DinoLogger.Error(ex.Message);
			}
			if (list != null)
			{
				_fileToData[file] = list;
				ResetToggleInfos();
				RefreshLocks();
			}
		}

		private static void RefreshLocks()
		{
			GearLockManager.Current.SetupAllowedGearsForActiveRundown();
		}

		private GearToggleManager()
		{
			string text = Path.Combine(MTFOWrapper.CustomPath, "ProgressionGear", "GearToggle");
			if (!Directory.Exists(text))
			{
				DinoLogger.Log("No GearToggle directory detected. Creating template.");
				Directory.CreateDirectory(text);
				StreamWriter streamWriter = File.CreateText(Path.Combine(text, "Template.json"));
				streamWriter.WriteLine(PWJson.Serialize(GearToggleData.Template));
				streamWriter.Flush();
				streamWriter.Close();
			}
			else
			{
				DinoLogger.Log("GearToggle directory detected.");
			}
			foreach (string item in Directory.EnumerateFiles(text, "*.json", SearchOption.AllDirectories))
			{
				string content = File.ReadAllText(item);
				ReadFileContent(item, content);
			}
			SafeFileSystemWatcher obj = SafeFileSystemWatcher.Create(text, new string[1] { "*.json" }, true);
			obj.OnCreated += FileCreated;
			obj.OnChanged += FileChanged;
			obj.OnDeleted += FileDeleted;
			obj.OnRenamed += FileRenamed;
		}

		internal void Init()
		{
			MTFOHotReloadAPI.OnHotReload += ResetToggleInfos;
		}

		public bool IsVisibleID(uint id)
		{
			if (_idToInfo.TryGetValue(id, out var value))
			{
				return value.ids[0] == id;
			}
			return true;
		}

		public bool HasRelatedIDs(uint id)
		{
			return _idToInfo.ContainsKey(id);
		}

		public ToggleInfo GetToggleInfo(uint id)
		{
			return _idToInfo.GetValueOrDefault(id);
		}

		public bool TryGetToggleInfo(uint id, [MaybeNullWhen(false)] out ToggleInfo toggleInfo)
		{
			return _idToInfo.TryGetValue(id, out toggleInfo);
		}

		public List<GearToggleData> GetData()
		{
			List<GearToggleData> list = new List<GearToggleData>(_fileToData.Values.Sum((List<GearToggleData> list2) => list2.Count));
			IEnumerator<GearToggleData> enumerator = GetEnumerator();
			while (enumerator.MoveNext())
			{
				list.Add(enumerator.Current);
			}
			return list;
		}

		public IEnumerator<GearToggleData> GetEnumerator()
		{
			return new DictListEnumerator<GearToggleData>(_fileToData);
		}

		public void RemoveFromToggleInfos(uint id)
		{
			if (_idToInfo.TryGetValue(id, out var value))
			{
				value.ids.Remove(id);
				if (value.ids.Count == 1)
				{
					_idToInfo.Remove(value.ids[0]);
				}
				_idToInfo.Remove(id);
			}
		}

		public void ResetToggleInfos()
		{
			_idToInfo.Clear();
			HashSet<uint> hashSet = new HashSet<uint>();
			IEnumerator<GearToggleData> enumerator = GetEnumerator();
			while (enumerator.MoveNext())
			{
				GearToggleData current = enumerator.Current;
				if (current.OfflineIDs.Count <= 1)
				{
					continue;
				}
				List<uint> list = new List<uint>(current.OfflineIDs.Count);
				foreach (uint offlineID in current.OfflineIDs)
				{
					if (hashSet.Add(offlineID))
					{
						list.Add(offlineID);
						continue;
					}
					DinoLogger.Warning($"Duplicate ID {offlineID} detected in toggle data. Removed from {current.Name}");
				}
				if (list.Count <= 1)
				{
					continue;
				}
				RemoveInvalidGear(list, current.Name);
				if (list.Count <= 1)
				{
					continue;
				}
				ToggleInfo value = new ToggleInfo
				{
					ids = list,
					text = current.ButtonText,
					reverse = current.ReverseOrder
				};
				foreach (uint item in list)
				{
					_idToInfo[item] = value;
				}
			}
		}

		private void RemoveInvalidGear(List<uint> relatedIDs, string name)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)GearLockManager.Current.VanillaGearManager == (Object)null)
			{
				return;
			}
			while (relatedIDs.Count > 1)
			{
				foreach (var (value, dictionary) in GearLockManager.Current.GearSlots)
				{
					if (!dictionary.ContainsKey(relatedIDs[0]))
					{
						continue;
					}
					for (int num = relatedIDs.Count - 1; num >= 1; num--)
					{
						uint num2 = relatedIDs[num];
						if (!dictionary.ContainsKey(num2))
						{
							DinoLogger.Warning($"ID {num2} removed from toggle data {name} since it is not of type {value}");
							relatedIDs.RemoveAt(num);
						}
					}
					return;
				}
				DinoLogger.Warning($"ID {relatedIDs[0]} removed from toggle data {name} since it does not exist.");
				relatedIDs.RemoveAt(0);
			}
		}
	}
	public struct ToggleInfo
	{
		public List<uint> ids;

		public LocalizedText[] text;

		public bool reverse;
	}
}
namespace ProgressionGear.Dependencies
{
	internal static class EOSWrapper
	{
		public const string INAS_GUID = "Inas.ExtraObjectiveSetup";

		public const string AMOR_GUID = "Amor.ExcellentObjectiveSetup";

		private static readonly bool _isAmor;

		public static bool HasEOS { get; private set; }

		static EOSWrapper()
		{
			if (((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("Inas.ExtraObjectiveSetup"))
			{
				HasEOS = true;
			}
			else if (((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("Amor.ExcellentObjectiveSetup"))
			{
				HasEOS = true;
				_isAmor = true;
			}
			else
			{
				HasEOS = false;
			}
		}

		public static void CacheLocks(ref HashSet<uint>? whitelist, HashSet<uint> blacklist)
		{
			if (HasEOS)
			{
				if (_isAmor)
				{
					CacheLocksEOS_Amor(ref whitelist, blacklist);
				}
				else
				{
					CacheLocksEOS_Inas(ref whitelist, blacklist);
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void CacheLocksEOS_Inas(ref HashSet<uint>? whitelist, HashSet<uint> blacklist)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			ExpeditionDefinition definition = ExpeditionDefinitionManager.Current.GetDefinition(ExpeditionDefinitionManager.Current.CurrentMainLevelLayout);
			if (definition == null || definition.ExpeditionGears == null)
			{
				return;
			}
			if ((int)definition.ExpeditionGears.Mode == 0)
			{
				if (whitelist == null)
				{
					whitelist = new HashSet<uint>();
				}
				whitelist.EnsureCapacity(definition.ExpeditionGears.GearIds.Count + whitelist.Count);
				whitelist.UnionWith(definition.ExpeditionGears.GearIds);
			}
			else
			{
				blacklist.EnsureCapacity(definition.ExpeditionGears.GearIds.Count + blacklist.Count);
				blacklist.UnionWith(definition.ExpeditionGears.GearIds);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void CacheLocksEOS_Amor(ref HashSet<uint>? whitelist, HashSet<uint> blacklist)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			ExpeditionDefinition val = default(ExpeditionDefinition);
			if (!BaseManager<ExpeditionDefinitionManager>.Current.TryGetDefinition(BaseManager.CurrentMainLevelLayout, ref val) || val.ExpeditionGears == null)
			{
				return;
			}
			if ((int)val.ExpeditionGears.Mode == 0)
			{
				if (whitelist == null)
				{
					whitelist = new HashSet<uint>();
				}
				whitelist.EnsureCapacity(val.ExpeditionGears.GearIds.Count + whitelist.Count);
				whitelist.UnionWith(val.ExpeditionGears.GearIds);
			}
			else
			{
				blacklist.EnsureCapacity(val.ExpeditionGears.GearIds.Count + blacklist.Count);
				blacklist.UnionWith(val.ExpeditionGears.GearIds);
			}
		}
	}
	internal static class LocalProgressionWrapper
	{
		public const string GUID = "Inas.LocalProgression";

		public static bool HasLocalProgression { get; private set; }

		static LocalProgressionWrapper()
		{
			HasLocalProgression = ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("Inas.LocalProgression");
		}

		public static ProgressionData GetProgressionDataLP(uint id, eRundownTier tier, int index)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!HasLocalProgression)
			{
				return new ProgressionData();
			}
			ExpeditionProgressionData expeditionLP = LocalProgressionManager.Current.GetExpeditionLP(id, tier, index);
			return new ProgressionData(expeditionLP.ExpeditionKey, expeditionLP.MainCompletionCount, expeditionLP.SecondaryCompletionCount, expeditionLP.ThirdCompletionCount, expeditionLP.AllClearCount, expeditionLP.NoBoosterAllClearCount);
		}
	}
	internal static class MTFOWrapper
	{
		public const string PLUGIN_GUID = "com.dak.MTFO";

		public static string GameDataPath => MTFOPathAPI.RundownPath;

		public static string CustomPath => MTFOPathAPI.CustomPath;

		public static bool HasCustomContent => MTFOPathAPI.HasRundownPath;
	}
	internal static class PartialDataWrapper
	{
		public const string PLUGIN_GUID = "MTFO.Extension.PartialBlocks";

		public static readonly bool HasPartialData;

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

		static PartialDataWrapper()
		{
			if (!((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("MTFO.Extension.PartialBlocks", out var value))
			{
				return;
			}
			try
			{
				PersistentIDConverter = (JsonConverter)Activator.CreateInstance((((value == null) ? null : value.Instance?.GetType()?.Assembly) ?? throw new Exception("Assembly is Missing!")).GetTypes().First((Type t) => t.Name == "PersistentIDConverter") ?? throw new Exception("Unable to Find PersistentIDConverter Class"));
				HasPartialData = true;
			}
			catch (Exception value2)
			{
				DinoLogger.Error($"Exception thrown while reading data from MTFO_Extension_PartialData:\n{value2}");
			}
		}
	}
}