Decompiled source of CosmeticPresetExtender v4.0.0

CosmeticPresetExtender.dll

Decompiled 14 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOJP.CosmeticPresetExtender
{
	[BepInPlugin("REPOJP.CosmeticPresetExtender", "CosmeticPresetExtender", "4.0.0")]
	public class CosmeticPresetExtenderPlugin : BaseUnityPlugin
	{
		[Serializable]
		private class ExtendedPresetStore
		{
			public int version = 2;

			public int columns = 7;

			public int vanillaSlots = 28;

			public int currentRows = 10;

			public int currentSlots = 70;

			public string updatedAtUtc = "";

			public List<ExtendedPresetEntry> presets = new List<ExtendedPresetEntry>();

			public List<LegacyPresetEntry> cosmeticPresets = new List<LegacyPresetEntry>();

			public List<LegacyPresetEntry> colorPresets = new List<LegacyPresetEntry>();
		}

		[Serializable]
		private class ExtendedPresetEntry
		{
			public int index;

			public List<int> cosmetics = new List<int>();

			public List<int> colors = new List<int>();

			public string updatedAtUtc = "";

			public string hash = "";

			public ExtendedPresetEntry()
			{
			}

			public ExtendedPresetEntry(int index, List<int> cosmetics, List<int> colors, string updatedAtUtc, string hash)
			{
				this.index = index;
				this.cosmetics = CopyValues(cosmetics);
				this.colors = CopyValues(colors);
				this.updatedAtUtc = updatedAtUtc;
				this.hash = (string.IsNullOrEmpty(hash) ? BuildPresetHash(cosmetics, colors) : hash);
			}
		}

		[Serializable]
		private class LegacyPresetEntry
		{
			public int index;

			public List<int> values = new List<int>();

			public LegacyPresetEntry()
			{
			}

			public LegacyPresetEntry(int index, List<int> values)
			{
				this.index = index;
				this.values = CopyValues(values);
			}
		}

		private class SaveState
		{
			public string reason;

			public int targetSlots;

			public List<List<int>> restoreCosmeticPresets;

			public List<List<int>> restoreColorPresets;
		}

		[HarmonyPatch(typeof(MetaManager), "Awake")]
		private static class MetaManagerAwakePatch
		{
			private static void Prefix(MetaManager __instance)
			{
				if (!IsEnabled())
				{
					return;
				}
				try
				{
					SetPresetSlotsField(__instance, GetTargetSlots());
				}
				catch (Exception ex)
				{
					WriteFailureLog("MetaManager.Awake Prefix", ex);
				}
			}

			private static void Postfix(MetaManager __instance)
			{
				EnsurePresetRuntimeSlots(__instance, mergeExtendedStore: false, "MetaManager.Awake Postfix");
			}
		}

		[HarmonyPatch(typeof(MetaManager), "Load")]
		private static class MetaManagerLoadPatch
		{
			private static void Prefix(MetaManager __instance)
			{
				EnsurePresetRuntimeSlots(__instance, mergeExtendedStore: false, "MetaManager.Load Prefix");
			}

			private static void Postfix(MetaManager __instance)
			{
				EnsurePresetRuntimeSlots(__instance, mergeExtendedStore: true, "MetaManager.Load Postfix");
			}
		}

		[HarmonyPatch(typeof(MetaManager), "Save")]
		private static class MetaManagerSavePatch
		{
			private static void Prefix(MetaManager __instance, ref SaveState __state)
			{
				if (!IsEnabled() || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				try
				{
					EnsurePresetRuntimeSlots(__instance, mergeExtendedStore: false, "MetaManager.Save Prefix");
					__state = BuildSaveState(__instance, insideMetaReset ? "MetaManager.Save inside Reset" : "MetaManager.Save");
					if (__state == null)
					{
						return;
					}
					if (!insideMetaReset || !ProtectExtendedSlotsOnReset())
					{
						SaveExtendedStoreFromRuntime(__instance, __state.restoreCosmeticPresets, __state.restoreColorPresets, GetTargetSlots(), createHistory: false, __state.reason);
					}
					if (insideMetaReset && ProtectExtendedSlotsOnReset())
					{
						ExtendedPresetStore extendedPresetStore = LoadExtendedStore(allowBackupRecovery: true);
						NormalizeStore(extendedPresetStore);
						Dictionary<int, ExtendedPresetEntry> dictionary = ToEntryMap(extendedPresetStore.presets);
						for (int i = 28; i < __state.targetSlots; i++)
						{
							__state.restoreCosmeticPresets[i] = new List<int>();
							__state.restoreColorPresets[i] = new List<int>();
							if (dictionary.ContainsKey(i))
							{
								__state.restoreCosmeticPresets[i] = CopyValues(dictionary[i].cosmetics);
								__state.restoreColorPresets[i] = CopyValues(dictionary[i].colors);
							}
						}
					}
					PrepareVanillaOnlySave(__instance, __state);
				}
				catch (Exception ex)
				{
					WriteFailureLog("MetaManager.Save Prefix", ex);
				}
			}

			private static Exception Finalizer(MetaManager __instance, SaveState __state, Exception __exception)
			{
				try
				{
					if (IsEnabled() && __state != null)
					{
						RestoreRuntimeAfterVanillaSave(__instance, __state);
					}
				}
				catch (Exception ex)
				{
					WriteFailureLog("MetaManager.Save Finalizer", ex);
				}
				return __exception;
			}
		}

		[HarmonyPatch(typeof(MetaManager), "Reset")]
		private static class MetaManagerResetPatch
		{
			private static void Prefix(MetaManager __instance)
			{
				if (!IsEnabled())
				{
					return;
				}
				try
				{
					EnsurePresetRuntimeSlots(__instance, mergeExtendedStore: false, "MetaManager.Reset Prefix");
					SaveExtendedPresetsNow(createHistory: true, "before_meta_reset");
					insideMetaReset = true;
				}
				catch (Exception ex)
				{
					insideMetaReset = true;
					WriteFailureLog("MetaManager.Reset Prefix", ex);
				}
			}

			private static void Postfix(MetaManager __instance)
			{
				try
				{
					if (IsEnabled())
					{
						insideMetaReset = false;
						if (!ProtectExtendedSlotsOnReset())
						{
							ClearExtendedStore(createHistory: true, "meta_reset_clear_extended");
						}
						EnsurePresetRuntimeSlots(__instance, ProtectExtendedSlotsOnReset(), "MetaManager.Reset Postfix");
					}
				}
				catch (Exception ex)
				{
					WriteFailureLog("MetaManager.Reset Postfix", ex);
				}
				finally
				{
					insideMetaReset = false;
				}
			}

			private static Exception Finalizer(Exception __exception)
			{
				insideMetaReset = false;
				return __exception;
			}
		}

		[HarmonyPatch(typeof(MetaManager), "CosmeticPresetSet")]
		private static class MetaManagerCosmeticPresetSetPatch
		{
			private static void Prefix(MetaManager __instance, int _index)
			{
				if (_index >= 0)
				{
					EnsurePresetRuntimeSlotsForIndex(__instance, _index, "MetaManager.CosmeticPresetSet Prefix");
				}
			}

			private static void Postfix(MetaManager __instance, int _index)
			{
				if (!IsEnabled() || (Object)(object)__instance == (Object)null || _index < 28)
				{
					return;
				}
				try
				{
					List<List<int>> presetList = GetPresetList(__instance, cosmeticPresetsField);
					List<List<int>> presetList2 = GetPresetList(__instance, colorPresetsField);
					SaveExtendedStoreFromRuntime(__instance, presetList, presetList2, GetTargetSlots(), createHistory: false, "CosmeticPresetSet " + _index);
				}
				catch (Exception ex)
				{
					WriteFailureLog("MetaManager.CosmeticPresetSet Postfix", ex);
				}
			}
		}

		[HarmonyPatch(typeof(MenuPageCosmetics), "RefreshScrollContent")]
		private static class MenuPageCosmeticsRefreshScrollContentPatch
		{
			private static void Prefix()
			{
				if ((Object)(object)MetaManager.instance != (Object)null)
				{
					EnsurePresetRuntimeSlots(MetaManager.instance, mergeExtendedStore: true, "MenuPageCosmetics.RefreshScrollContent Prefix");
				}
			}

			private static void Postfix(MenuPageCosmetics __instance)
			{
				RefreshPresetGridLayout(__instance);
			}
		}

		[HarmonyPatch(typeof(MenuElementCosmeticPreset), "Start")]
		private static class MenuElementCosmeticPresetStartPatch
		{
			private static void Prefix(MenuElementCosmeticPreset __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)MetaManager.instance == (Object)null))
				{
					EnsurePresetRuntimeSlotsForIndex(MetaManager.instance, __instance.presetIndex, "MenuElementCosmeticPreset.Start Prefix");
				}
			}
		}

		[HarmonyPatch(typeof(MenuElementCosmeticPreset), "TogglePreset")]
		private static class MenuElementCosmeticPresetTogglePresetPatch
		{
			private static void Prefix(MenuElementCosmeticPreset __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)MetaManager.instance == (Object)null))
				{
					EnsurePresetRuntimeSlotsForIndex(MetaManager.instance, __instance.presetIndex, "MenuElementCosmeticPreset.TogglePreset Prefix");
				}
			}
		}

		[HarmonyPatch(typeof(MenuElementCosmeticPreset), "DeletePreset")]
		private static class MenuElementCosmeticPresetDeletePresetPatch
		{
			private static void Prefix(MenuElementCosmeticPreset __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)MetaManager.instance == (Object)null))
				{
					EnsurePresetRuntimeSlotsForIndex(MetaManager.instance, __instance.presetIndex, "MenuElementCosmeticPreset.DeletePreset Prefix");
				}
			}
		}

		[HarmonyPatch(typeof(DebugCommandHandler), "Start")]
		private static class DebugCommandHandlerStartPatch
		{
			private static void Postfix(DebugCommandHandler __instance)
			{
				RegisterCommands(__instance);
			}
		}

		public const string PluginGuid = "REPOJP.CosmeticPresetExtender";

		public const string PluginName = "CosmeticPresetExtender";

		public const string PluginVersion = "4.0.0";

		private const int VanillaColumns = 7;

		private const int VanillaRows = 4;

		private const int VanillaSlots = 28;

		private const int MinRows = 4;

		private const int MaxRows = 100;

		private const int DefaultRows = 10;

		private const float PresetCellWidth = 60f;

		private const float PresetCellHeight = 140f;

		private static CosmeticPresetExtenderPlugin instance;

		private static ManualLogSource logSource;

		private static Harmony harmony;

		private static ConfigEntry<bool> configEnabled;

		private static ConfigEntry<int> configPresetRows;

		private static ConfigEntry<bool> configProtectExtendedSlotsOnReset;

		private static ConfigEntry<int> configBackupHistoryCount;

		private static ConfigEntry<bool> configDetailedLog;

		private static readonly FieldInfo presetSlotsField = AccessTools.Field(typeof(MetaManager), "presetSlots");

		private static readonly FieldInfo cosmeticPresetsField = AccessTools.Field(typeof(MetaManager), "cosmeticPresets");

		private static readonly FieldInfo colorPresetsField = AccessTools.Field(typeof(MetaManager), "colorPresets");

		private static readonly FieldInfo colorsEquippedField = AccessTools.Field(typeof(MetaManager), "colorsEquipped");

		private static readonly FieldInfo cosmeticAssetsField = AccessTools.Field(typeof(MetaManager), "cosmeticAssets");

		private static readonly FieldInfo colorsField = AccessTools.Field(typeof(MetaManager), "colors");

		private static bool insideMetaReset;

		private static bool commandRegistered;

		private static string StoreDirectory => Path.Combine(Paths.ConfigPath, "REPOJP.CosmeticPresetExtender");

		private static string StoreFilePath => Path.Combine(StoreDirectory, "ExtendedPresets.json");

		private static string StoreBackupFilePath => Path.Combine(StoreDirectory, "ExtendedPresets.json.bak");

		private static string HistoryDirectory => Path.Combine(StoreDirectory, "history");

		private void Awake()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			try
			{
				instance = this;
				logSource = ((BaseUnityPlugin)this).Logger;
				((Component)this).transform.parent = null;
				((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				configEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enables this mod.このMODを有効化します");
				configPresetRows = ((BaseUnityPlugin)this).Config.Bind<int>("General", "PresetRows", 10, new ConfigDescription("Cosmetic preset rows. 7 columns are fixed.コスメプリセットの行数。7列固定", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 100), Array.Empty<object>()));
				configProtectExtendedSlotsOnReset = ((BaseUnityPlugin)this).Config.Bind<bool>("Save Safety", "ProtectExtendedSlotsOnReset", true, "Keeps slot 29 and later when vanilla meta progress is reset.バニラのメタ進行リセット時も29枠目以降を保持します");
				configBackupHistoryCount = ((BaseUnityPlugin)this).Config.Bind<int>("Save Safety", "BackupHistoryCount", 10, new ConfigDescription("Maximum history backup files.履歴バックアップファイルの最大保持数", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
				configDetailedLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DetailedLog", false, "Outputs detailed debug logs.詳細ログを出力します");
				harmony = new Harmony("REPOJP.CosmeticPresetExtender");
				harmony.PatchAll(typeof(CosmeticPresetExtenderPlugin).Assembly);
				WriteLog("Loaded. Rows=" + GetTargetRows() + " Slots=" + GetTargetSlots() + " VanillaSaveSlots=" + 28);
			}
			catch (Exception ex)
			{
				if (logSource != null)
				{
					logSource.LogError((object)("Failure: Awake\n" + ex));
				}
			}
		}

		private void OnDestroy()
		{
			try
			{
				if (harmony != null)
				{
					harmony.UnpatchSelf();
					harmony = null;
				}
			}
			catch (Exception ex)
			{
				if (logSource != null)
				{
					logSource.LogError((object)("Failure: OnDestroy\n" + ex));
				}
			}
		}

		private static bool IsEnabled()
		{
			return configEnabled == null || configEnabled.Value;
		}

		private static int GetTargetRows()
		{
			int num = 10;
			if (configPresetRows != null)
			{
				num = configPresetRows.Value;
			}
			return Mathf.Clamp(num, 4, 100);
		}

		private static int GetTargetSlots()
		{
			return GetTargetRows() * 7;
		}

		private static int GetHistoryLimit()
		{
			int num = 10;
			if (configBackupHistoryCount != null)
			{
				num = configBackupHistoryCount.Value;
			}
			return Mathf.Clamp(num, 0, 100);
		}

		private static bool ProtectExtendedSlotsOnReset()
		{
			return configProtectExtendedSlotsOnReset == null || configProtectExtendedSlotsOnReset.Value;
		}

		private static void WriteLog(string message)
		{
			if (logSource != null)
			{
				logSource.LogInfo((object)message);
			}
		}

		private static void WriteDetailLog(string message)
		{
			if (configDetailedLog != null && configDetailedLog.Value && logSource != null)
			{
				logSource.LogInfo((object)message);
			}
		}

		private static void WriteFailureLog(string message, Exception ex)
		{
			if (logSource != null)
			{
				logSource.LogError((object)("Failure: " + message + "\n" + ex));
			}
		}

		private static void SetPresetSlotsField(MetaManager manager, int slots)
		{
			if (!((Object)(object)manager == (Object)null) && !(presetSlotsField == null))
			{
				presetSlotsField.SetValue(manager, slots);
			}
		}

		private static List<List<int>> GetPresetList(MetaManager manager, FieldInfo field)
		{
			if ((Object)(object)manager == (Object)null || field == null)
			{
				return null;
			}
			return field.GetValue(manager) as List<List<int>>;
		}

		private static void SetPresetList(MetaManager manager, FieldInfo field, List<List<int>> value)
		{
			if (!((Object)(object)manager == (Object)null) && !(field == null))
			{
				field.SetValue(manager, value);
			}
		}

		private static int[] GetColorsEquipped(MetaManager manager)
		{
			if ((Object)(object)manager == (Object)null || colorsEquippedField == null)
			{
				return null;
			}
			return colorsEquippedField.GetValue(manager) as int[];
		}

		private static int GetCosmeticAssetCount(MetaManager manager)
		{
			if ((Object)(object)manager == (Object)null || cosmeticAssetsField == null)
			{
				return 0;
			}
			object value = cosmeticAssetsField.GetValue(manager);
			if (!(value is ICollection collection))
			{
				return 0;
			}
			return collection.Count;
		}

		private static int GetColorCount(MetaManager manager)
		{
			if ((Object)(object)manager == (Object)null || colorsField == null)
			{
				return 0;
			}
			object value = colorsField.GetValue(manager);
			if (!(value is ICollection collection))
			{
				return 0;
			}
			return collection.Count;
		}

		private static void EnsurePresetRuntimeSlots(MetaManager manager, bool mergeExtendedStore, string reason)
		{
			if (!IsEnabled() || (Object)(object)manager == (Object)null)
			{
				return;
			}
			try
			{
				int targetSlots = GetTargetSlots();
				SetPresetSlotsField(manager, targetSlots);
				List<List<int>> list = GetPresetList(manager, cosmeticPresetsField);
				List<List<int>> list2 = GetPresetList(manager, colorPresetsField);
				if (list == null)
				{
					list = new List<List<int>>();
					SetPresetList(manager, cosmeticPresetsField, list);
				}
				if (list2 == null)
				{
					list2 = new List<List<int>>();
					SetPresetList(manager, colorPresetsField, list2);
				}
				ExpandList(list, targetSlots);
				ExpandList(list2, targetSlots);
				NormalizeLists(manager, list, list2);
				if (mergeExtendedStore)
				{
					MergeExtendedStoreIntoRuntime(manager, list, list2, forceOverwrite: false);
					NormalizeLists(manager, list, list2);
				}
				WriteDetailLog("EnsurePresetRuntimeSlots: " + reason + " Rows=" + GetTargetRows() + " Slots=" + targetSlots);
			}
			catch (Exception ex)
			{
				WriteFailureLog("EnsurePresetRuntimeSlots / " + reason, ex);
			}
		}

		private static void EnsurePresetRuntimeSlotsForIndex(MetaManager manager, int index, string reason)
		{
			if (!IsEnabled() || (Object)(object)manager == (Object)null || index < 0)
			{
				return;
			}
			try
			{
				int num = Mathf.Max(GetTargetSlots(), index + 1);
				SetPresetSlotsField(manager, num);
				List<List<int>> list = GetPresetList(manager, cosmeticPresetsField);
				List<List<int>> list2 = GetPresetList(manager, colorPresetsField);
				if (list == null)
				{
					list = new List<List<int>>();
					SetPresetList(manager, cosmeticPresetsField, list);
				}
				if (list2 == null)
				{
					list2 = new List<List<int>>();
					SetPresetList(manager, colorPresetsField, list2);
				}
				ExpandList(list, num);
				ExpandList(list2, num);
				NormalizeLists(manager, list, list2);
				WriteDetailLog("EnsurePresetRuntimeSlotsForIndex: " + reason + " Index=" + index);
			}
			catch (Exception ex)
			{
				WriteFailureLog("EnsurePresetRuntimeSlotsForIndex / " + reason, ex);
			}
		}

		private static void ExpandList(List<List<int>> list, int targetCount)
		{
			if (list == null)
			{
				return;
			}
			while (list.Count < targetCount)
			{
				list.Add(new List<int>());
			}
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i] == null)
				{
					list[i] = new List<int>();
				}
			}
		}

		private static List<List<int>> ClonePresetList(List<List<int>> source, int targetCount)
		{
			List<List<int>> list = new List<List<int>>();
			for (int i = 0; i < targetCount; i++)
			{
				if (source != null && i < source.Count && source[i] != null)
				{
					list.Add(new List<int>(source[i]));
				}
				else
				{
					list.Add(new List<int>());
				}
			}
			return list;
		}

		private static List<List<int>> CloneFirstSlots(List<List<int>> source, int count)
		{
			List<List<int>> list = new List<List<int>>();
			for (int i = 0; i < count; i++)
			{
				if (source != null && i < source.Count && source[i] != null)
				{
					list.Add(new List<int>(source[i]));
				}
				else
				{
					list.Add(new List<int>());
				}
			}
			return list;
		}

		private static List<int> CopyValues(List<int> source)
		{
			if (source == null)
			{
				return new List<int>();
			}
			return new List<int>(source);
		}

		private static bool HasPresetData(List<int> cosmetics, List<int> colors)
		{
			bool flag = cosmetics != null && cosmetics.Count > 0;
			bool flag2 = colors != null && colors.Count > 0;
			return flag || flag2;
		}

		private static void NormalizeLists(MetaManager manager, List<List<int>> cosmeticPresets, List<List<int>> colorPresets)
		{
			if ((Object)(object)manager == (Object)null || cosmeticPresets == null || colorPresets == null)
			{
				return;
			}
			int targetCount = Mathf.Max(GetTargetSlots(), Mathf.Max(cosmeticPresets.Count, colorPresets.Count));
			ExpandList(cosmeticPresets, targetCount);
			ExpandList(colorPresets, targetCount);
			int cosmeticAssetCount = GetCosmeticAssetCount(manager);
			int colorCount = GetColorCount(manager);
			int[] colorsEquipped = GetColorsEquipped(manager);
			int num = ((colorsEquipped != null) ? colorsEquipped.Length : 0);
			for (int i = 0; i < cosmeticPresets.Count; i++)
			{
				List<int> list = cosmeticPresets[i];
				if (list == null)
				{
					cosmeticPresets[i] = new List<int>();
					continue;
				}
				for (int num2 = list.Count - 1; num2 >= 0; num2--)
				{
					int num3 = list[num2];
					if (num3 < 0 || (cosmeticAssetCount > 0 && num3 >= cosmeticAssetCount))
					{
						list.RemoveAt(num2);
					}
				}
			}
			for (int j = 0; j < colorPresets.Count; j++)
			{
				List<int> list2 = colorPresets[j];
				if (list2 == null)
				{
					colorPresets[j] = new List<int>();
					list2 = colorPresets[j];
				}
				bool flag = HasPresetData((j < cosmeticPresets.Count) ? cosmeticPresets[j] : null, list2);
				if (num > 0 && flag)
				{
					while (list2.Count < num)
					{
						list2.Add(0);
					}
					while (list2.Count > num)
					{
						list2.RemoveAt(list2.Count - 1);
					}
				}
				for (int k = 0; k < list2.Count; k++)
				{
					if (list2[k] < 0)
					{
						list2[k] = 0;
					}
					if (colorCount > 0 && list2[k] >= colorCount)
					{
						list2[k] = 0;
					}
				}
			}
		}

		private static void MergeExtendedStoreIntoRuntime(MetaManager manager, List<List<int>> cosmeticPresets, List<List<int>> colorPresets, bool forceOverwrite)
		{
			if (!IsEnabled() || (Object)(object)manager == (Object)null || cosmeticPresets == null || colorPresets == null)
			{
				return;
			}
			try
			{
				ExtendedPresetStore extendedPresetStore = LoadExtendedStore(allowBackupRecovery: true);
				NormalizeStore(extendedPresetStore);
				int targetSlots = GetTargetSlots();
				ExpandList(cosmeticPresets, targetSlots);
				ExpandList(colorPresets, targetSlots);
				Dictionary<int, ExtendedPresetEntry> dictionary = ToEntryMap(extendedPresetStore.presets);
				for (int i = 28; i < targetSlots; i++)
				{
					if (!dictionary.ContainsKey(i))
					{
						continue;
					}
					ExtendedPresetEntry extendedPresetEntry = dictionary[i];
					if (!HasPresetData(cosmeticPresets[i], colorPresets[i]) || forceOverwrite)
					{
						string text = BuildPresetHash(cosmeticPresets[i], colorPresets[i]);
						cosmeticPresets[i] = CopyValues(extendedPresetEntry.cosmetics);
						colorPresets[i] = CopyValues(extendedPresetEntry.colors);
						string text2 = BuildPresetHash(cosmeticPresets[i], colorPresets[i]);
						if (text != text2)
						{
							DeletePresetIcon(i);
						}
					}
				}
				WriteDetailLog("Extended preset store merged. Entries=" + extendedPresetStore.presets.Count);
			}
			catch (Exception ex)
			{
				WriteFailureLog("MergeExtendedStoreIntoRuntime", ex);
			}
		}

		private static void SaveExtendedStoreFromRuntime(MetaManager manager, List<List<int>> fullCosmeticPresets, List<List<int>> fullColorPresets, int visibleSlots, bool createHistory, string reason)
		{
			if (!IsEnabled() || (Object)(object)manager == (Object)null)
			{
				return;
			}
			try
			{
				ExtendedPresetStore extendedPresetStore = LoadExtendedStore(allowBackupRecovery: true);
				NormalizeStore(extendedPresetStore);
				Dictionary<int, ExtendedPresetEntry> dictionary = ToEntryMap(extendedPresetStore.presets);
				int num = Mathf.Max(28, visibleSlots);
				for (int i = 28; i < num; i++)
				{
					List<int> list = ((fullCosmeticPresets != null && i < fullCosmeticPresets.Count && fullCosmeticPresets[i] != null) ? fullCosmeticPresets[i] : new List<int>());
					List<int> list2 = ((fullColorPresets != null && i < fullColorPresets.Count && fullColorPresets[i] != null) ? fullColorPresets[i] : new List<int>());
					string text = BuildPresetHash(list, list2);
					if (dictionary.TryGetValue(i, out var value) && value != null && value.hash == text)
					{
						value.cosmetics = CopyValues(list);
						value.colors = CopyValues(list2);
					}
					else
					{
						dictionary[i] = new ExtendedPresetEntry(i, list, list2, DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"), text);
						DeletePresetIcon(i);
					}
				}
				extendedPresetStore.version = 2;
				extendedPresetStore.columns = 7;
				extendedPresetStore.vanillaSlots = 28;
				extendedPresetStore.currentRows = GetTargetRows();
				extendedPresetStore.currentSlots = GetTargetSlots();
				extendedPresetStore.updatedAtUtc = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
				extendedPresetStore.presets = ToSortedEntryList(dictionary);
				extendedPresetStore.cosmeticPresets = new List<LegacyPresetEntry>();
				extendedPresetStore.colorPresets = new List<LegacyPresetEntry>();
				WriteExtendedStore(extendedPresetStore, createHistory, reason);
				WriteDetailLog("Extended preset store saved. Reason=" + reason + " Entries=" + extendedPresetStore.presets.Count);
			}
			catch (Exception ex)
			{
				WriteFailureLog("SaveExtendedStoreFromRuntime / " + reason, ex);
			}
		}

		private static void ClearExtendedStore(bool createHistory, string reason)
		{
			try
			{
				ExtendedPresetStore store = LoadExtendedStore(allowBackupRecovery: true);
				NormalizeStore(store);
				if (createHistory)
				{
					WriteHistoryBackup(store, reason);
				}
				ExtendedPresetStore extendedPresetStore = new ExtendedPresetStore();
				extendedPresetStore.version = 2;
				extendedPresetStore.columns = 7;
				extendedPresetStore.vanillaSlots = 28;
				extendedPresetStore.currentRows = GetTargetRows();
				extendedPresetStore.currentSlots = GetTargetSlots();
				extendedPresetStore.updatedAtUtc = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
				WriteExtendedStore(extendedPresetStore, createHistory: false, reason);
			}
			catch (Exception ex)
			{
				WriteFailureLog("ClearExtendedStore / " + reason, ex);
			}
		}

		private static ExtendedPresetStore LoadExtendedStore(bool allowBackupRecovery)
		{
			try
			{
				if (TryReadStoreFile(StoreFilePath, out var data))
				{
					NormalizeStore(data);
					return data;
				}
				if (allowBackupRecovery && TryReadStoreFile(StoreBackupFilePath, out data))
				{
					NormalizeStore(data);
					RecoverPrimaryStoreFromBackup(data);
					return data;
				}
			}
			catch (Exception ex)
			{
				WriteFailureLog("LoadExtendedStore", ex);
			}
			return new ExtendedPresetStore();
		}

		private static bool TryReadStoreFile(string path, out ExtendedPresetStore data)
		{
			data = null;
			try
			{
				if (string.IsNullOrEmpty(path) || !File.Exists(path))
				{
					return false;
				}
				string text = File.ReadAllText(path, Encoding.UTF8);
				if (string.IsNullOrWhiteSpace(text))
				{
					return false;
				}
				ExtendedPresetStore extendedPresetStore = JsonUtility.FromJson<ExtendedPresetStore>(text);
				if (extendedPresetStore == null)
				{
					return false;
				}
				if (extendedPresetStore.presets == null && extendedPresetStore.cosmeticPresets == null && extendedPresetStore.colorPresets == null)
				{
					return false;
				}
				data = extendedPresetStore;
				NormalizeStore(data);
				return true;
			}
			catch (Exception ex)
			{
				WriteFailureLog("TryReadStoreFile: " + path, ex);
				return false;
			}
		}

		private static void RecoverPrimaryStoreFromBackup(ExtendedPresetStore backupData)
		{
			try
			{
				Directory.CreateDirectory(StoreDirectory);
				if (File.Exists(StoreFilePath))
				{
					string destFileName = StoreFilePath + ".corrupt_" + DateTime.Now.ToString("yyyyMMdd_HHmmss");
					File.Move(StoreFilePath, destFileName);
				}
				WriteExtendedStore(backupData, createHistory: false, "recover_from_bak");
				WriteLog("ExtendedPresets.json was recovered from .bak.");
			}
			catch (Exception ex)
			{
				WriteFailureLog("RecoverPrimaryStoreFromBackup", ex);
			}
		}

		private static void WriteExtendedStore(ExtendedPresetStore store, bool createHistory, string reason)
		{
			try
			{
				Directory.CreateDirectory(StoreDirectory);
				NormalizeStore(store);
				if (createHistory)
				{
					WriteHistoryBackup(store, reason);
				}
				string contents = JsonUtility.ToJson((object)store, true);
				string text = StoreFilePath + ".tmp";
				File.WriteAllText(text, contents, Encoding.UTF8);
				if (File.Exists(StoreFilePath))
				{
					File.Copy(StoreFilePath, StoreBackupFilePath, overwrite: true);
					File.Delete(StoreFilePath);
				}
				File.Move(text, StoreFilePath);
				CleanupHistoryBackups();
			}
			catch (Exception ex)
			{
				WriteFailureLog("WriteExtendedStore / " + reason, ex);
			}
		}

		private static void WriteHistoryBackup(ExtendedPresetStore store, string reason)
		{
			try
			{
				int historyLimit = GetHistoryLimit();
				if (historyLimit > 0)
				{
					Directory.CreateDirectory(HistoryDirectory);
					NormalizeStore(store);
					string text = SanitizeFileName(reason);
					string path = Path.Combine(HistoryDirectory, "ExtendedPresets_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + "_" + text + ".json");
					string contents = JsonUtility.ToJson((object)store, true);
					File.WriteAllText(path, contents, Encoding.UTF8);
					CleanupHistoryBackups();
				}
			}
			catch (Exception ex)
			{
				WriteFailureLog("WriteHistoryBackup / " + reason, ex);
			}
		}

		private static void CleanupHistoryBackups()
		{
			try
			{
				int historyLimit = GetHistoryLimit();
				if (historyLimit <= 0 || !Directory.Exists(HistoryDirectory))
				{
					return;
				}
				FileInfo[] files = new DirectoryInfo(HistoryDirectory).GetFiles("ExtendedPresets_*.json");
				Array.Sort(files, (FileInfo a, FileInfo b) => b.CreationTimeUtc.CompareTo(a.CreationTimeUtc));
				for (int i = historyLimit; i < files.Length; i++)
				{
					try
					{
						files[i].Delete();
					}
					catch
					{
					}
				}
			}
			catch (Exception ex)
			{
				WriteFailureLog("CleanupHistoryBackups", ex);
			}
		}

		private static string SanitizeFileName(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return "manual";
			}
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			string text = value;
			for (int i = 0; i < invalidFileNameChars.Length; i++)
			{
				text = text.Replace(invalidFileNameChars[i], '_');
			}
			return text.Replace(' ', '_');
		}

		private static void NormalizeStore(ExtendedPresetStore store)
		{
			if (store == null)
			{
				return;
			}
			if (store.presets == null)
			{
				store.presets = new List<ExtendedPresetEntry>();
			}
			if (store.cosmeticPresets == null)
			{
				store.cosmeticPresets = new List<LegacyPresetEntry>();
			}
			if (store.colorPresets == null)
			{
				store.colorPresets = new List<LegacyPresetEntry>();
			}
			if (store.presets.Count == 0 && (store.cosmeticPresets.Count > 0 || store.colorPresets.Count > 0))
			{
				Dictionary<int, LegacyPresetEntry> dictionary = ToLegacyEntryMap(store.cosmeticPresets);
				Dictionary<int, LegacyPresetEntry> dictionary2 = ToLegacyEntryMap(store.colorPresets);
				Dictionary<int, ExtendedPresetEntry> dictionary3 = new Dictionary<int, ExtendedPresetEntry>();
				foreach (int key in dictionary.Keys)
				{
					List<int> cosmetics = ((dictionary[key] != null) ? dictionary[key].values : new List<int>());
					List<int> colors = ((dictionary2.ContainsKey(key) && dictionary2[key] != null) ? dictionary2[key].values : new List<int>());
					dictionary3[key] = new ExtendedPresetEntry(key, cosmetics, colors, DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"), BuildPresetHash(cosmetics, colors));
				}
				foreach (int key2 in dictionary2.Keys)
				{
					if (!dictionary3.ContainsKey(key2))
					{
						List<int> colors2 = ((dictionary2[key2] != null) ? dictionary2[key2].values : new List<int>());
						dictionary3[key2] = new ExtendedPresetEntry(key2, new List<int>(), colors2, DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"), BuildPresetHash(new List<int>(), colors2));
					}
				}
				store.presets = ToSortedEntryList(dictionary3);
			}
			Dictionary<int, ExtendedPresetEntry> map = ToEntryMap(store.presets);
			store.presets = ToSortedEntryList(map);
		}

		private static Dictionary<int, LegacyPresetEntry> ToLegacyEntryMap(List<LegacyPresetEntry> entries)
		{
			Dictionary<int, LegacyPresetEntry> dictionary = new Dictionary<int, LegacyPresetEntry>();
			if (entries == null)
			{
				return dictionary;
			}
			foreach (LegacyPresetEntry entry in entries)
			{
				if (entry != null && entry.index >= 28)
				{
					dictionary[entry.index] = new LegacyPresetEntry(entry.index, entry.values);
				}
			}
			return dictionary;
		}

		private static Dictionary<int, ExtendedPresetEntry> ToEntryMap(List<ExtendedPresetEntry> entries)
		{
			Dictionary<int, ExtendedPresetEntry> dictionary = new Dictionary<int, ExtendedPresetEntry>();
			if (entries == null)
			{
				return dictionary;
			}
			foreach (ExtendedPresetEntry entry in entries)
			{
				if (entry != null && entry.index >= 28)
				{
					dictionary[entry.index] = new ExtendedPresetEntry(entry.index, entry.cosmetics, entry.colors, entry.updatedAtUtc, entry.hash);
				}
			}
			return dictionary;
		}

		private static List<ExtendedPresetEntry> ToSortedEntryList(Dictionary<int, ExtendedPresetEntry> map)
		{
			List<ExtendedPresetEntry> list = new List<ExtendedPresetEntry>();
			if (map == null)
			{
				return list;
			}
			List<int> list2 = new List<int>(map.Keys);
			list2.Sort();
			foreach (int item in list2)
			{
				ExtendedPresetEntry extendedPresetEntry = map[item];
				if (extendedPresetEntry != null && item >= 28)
				{
					if (string.IsNullOrEmpty(extendedPresetEntry.hash))
					{
						extendedPresetEntry.hash = BuildPresetHash(extendedPresetEntry.cosmetics, extendedPresetEntry.colors);
					}
					if (string.IsNullOrEmpty(extendedPresetEntry.updatedAtUtc))
					{
						extendedPresetEntry.updatedAtUtc = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
					}
					list.Add(new ExtendedPresetEntry(item, extendedPresetEntry.cosmetics, extendedPresetEntry.colors, extendedPresetEntry.updatedAtUtc, extendedPresetEntry.hash));
				}
			}
			return list;
		}

		private static string BuildPresetHash(List<int> cosmetics, List<int> colors)
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (cosmetics != null)
			{
				for (int i = 0; i < cosmetics.Count; i++)
				{
					if (i > 0)
					{
						stringBuilder.Append(',');
					}
					stringBuilder.Append(cosmetics[i].ToString());
				}
			}
			stringBuilder.Append('|');
			if (colors != null)
			{
				for (int j = 0; j < colors.Count; j++)
				{
					if (j > 0)
					{
						stringBuilder.Append(',');
					}
					stringBuilder.Append(colors[j].ToString());
				}
			}
			return stringBuilder.ToString();
		}

		private static void DeletePresetIcon(int presetIndex)
		{
			try
			{
				if (presetIndex < 0 || (Object)(object)MetaManager.instance == (Object)null)
				{
					return;
				}
				FieldInfo fieldInfo = AccessTools.Field(typeof(MetaManager), "presetCacheFolder");
				string text = "CosmeticsPresets";
				if (fieldInfo != null)
				{
					object value = fieldInfo.GetValue(MetaManager.instance);
					if (value is string && !string.IsNullOrEmpty((string)value))
					{
						text = (string)value;
					}
				}
				string path = Path.Combine(Application.persistentDataPath, "Cache", "Icons", text, presetIndex.ToString().ToLowerInvariant() + ".png");
				if (File.Exists(path))
				{
					File.Delete(path);
				}
			}
			catch (Exception ex)
			{
				WriteFailureLog("DeletePresetIcon", ex);
			}
		}

		private static void RefreshPresetGridLayout(MenuPageCosmetics menuPageCosmetics)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			if (!IsEnabled() || (Object)(object)menuPageCosmetics == (Object)null)
			{
				return;
			}
			try
			{
				if ((int)menuPageCosmetics.selectedTab != 1 || (Object)(object)menuPageCosmetics.sectionRootTransform == (Object)null)
				{
					return;
				}
				int targetSlots = GetTargetSlots();
				int num = Mathf.Max(4, Mathf.CeilToInt((float)targetSlots / 7f));
				MenuElementCosmeticSection[] componentsInChildren = ((Component)menuPageCosmetics.sectionRootTransform).GetComponentsInChildren<MenuElementCosmeticSection>(true);
				MenuElementCosmeticSection[] array = componentsInChildren;
				foreach (MenuElementCosmeticSection val in array)
				{
					if ((Object)(object)val == (Object)null || (Object)(object)val.cosmeticListTransform == (Object)null)
					{
						continue;
					}
					MenuElementCosmeticPreset componentInChildren = ((Component)val.cosmeticListTransform).GetComponentInChildren<MenuElementCosmeticPreset>(true);
					if ((Object)(object)componentInChildren == (Object)null)
					{
						continue;
					}
					GridLayoutGroup component = ((Component)val.cosmeticListTransform).GetComponent<GridLayoutGroup>();
					if (!((Object)(object)component == (Object)null))
					{
						component.constraint = (Constraint)1;
						component.constraintCount = 7;
						component.cellSize = new Vector2(60f, 140f);
						float num2 = component.cellSize.y * (float)num + component.spacing.y * (float)Mathf.Max(0, num - 1) + (float)((LayoutGroup)component).padding.top + (float)((LayoutGroup)component).padding.bottom;
						RectTransform component2 = ((Component)val.cosmeticListTransform).GetComponent<RectTransform>();
						if ((Object)(object)component2 != (Object)null)
						{
							component2.sizeDelta = new Vector2(component2.sizeDelta.x, num2);
							LayoutRebuilder.ForceRebuildLayoutImmediate(component2);
						}
						RectTransform component3 = ((Component)val).GetComponent<RectTransform>();
						if ((Object)(object)component3 != (Object)null)
						{
							component3.sizeDelta = new Vector2(component3.sizeDelta.x, num2);
							LayoutRebuilder.ForceRebuildLayoutImmediate(component3);
						}
					}
				}
			}
			catch (Exception ex)
			{
				WriteFailureLog("RefreshPresetGridLayout", ex);
			}
		}

		private static SaveState BuildSaveState(MetaManager manager, string reason)
		{
			if ((Object)(object)manager == (Object)null)
			{
				return null;
			}
			int targetSlots = GetTargetSlots();
			List<List<int>> presetList = GetPresetList(manager, cosmeticPresetsField);
			List<List<int>> presetList2 = GetPresetList(manager, colorPresetsField);
			ExpandList(presetList, targetSlots);
			ExpandList(presetList2, targetSlots);
			NormalizeLists(manager, presetList, presetList2);
			SaveState saveState = new SaveState();
			saveState.reason = reason;
			saveState.targetSlots = targetSlots;
			saveState.restoreCosmeticPresets = ClonePresetList(presetList, targetSlots);
			saveState.restoreColorPresets = ClonePresetList(presetList2, targetSlots);
			return saveState;
		}

		private static void PrepareVanillaOnlySave(MetaManager manager, SaveState state)
		{
			if (!((Object)(object)manager == (Object)null) && state != null)
			{
				List<List<int>> value = CloneFirstSlots(state.restoreCosmeticPresets, 28);
				List<List<int>> value2 = CloneFirstSlots(state.restoreColorPresets, 28);
				SetPresetList(manager, cosmeticPresetsField, value);
				SetPresetList(manager, colorPresetsField, value2);
				SetPresetSlotsField(manager, 28);
			}
		}

		private static void RestoreRuntimeAfterVanillaSave(MetaManager manager, SaveState state)
		{
			if (!((Object)(object)manager == (Object)null) && state != null)
			{
				SetPresetList(manager, cosmeticPresetsField, ClonePresetList(state.restoreCosmeticPresets, state.targetSlots));
				SetPresetList(manager, colorPresetsField, ClonePresetList(state.restoreColorPresets, state.targetSlots));
				SetPresetSlotsField(manager, state.targetSlots);
				EnsurePresetRuntimeSlots(manager, mergeExtendedStore: false, "RestoreRuntimeAfterVanillaSave / " + state.reason);
			}
		}

		private static void RestoreExtendedPresetsFromStoreNow(bool forceOverwrite, string reason)
		{
			try
			{
				if (!((Object)(object)MetaManager.instance == (Object)null))
				{
					EnsurePresetRuntimeSlots(MetaManager.instance, mergeExtendedStore: false, reason + " / before_restore");
					List<List<int>> presetList = GetPresetList(MetaManager.instance, cosmeticPresetsField);
					List<List<int>> presetList2 = GetPresetList(MetaManager.instance, colorPresetsField);
					MergeExtendedStoreIntoRuntime(MetaManager.instance, presetList, presetList2, forceOverwrite);
					NormalizeLists(MetaManager.instance, presetList, presetList2);
					WriteLog("Extended presets restored. Reason=" + reason);
				}
			}
			catch (Exception ex)
			{
				WriteFailureLog("RestoreExtendedPresetsFromStoreNow / " + reason, ex);
			}
		}

		private static void SaveExtendedPresetsNow(bool createHistory, string reason)
		{
			try
			{
				if (!((Object)(object)MetaManager.instance == (Object)null))
				{
					EnsurePresetRuntimeSlots(MetaManager.instance, mergeExtendedStore: false, reason + " / before_backup");
					List<List<int>> presetList = GetPresetList(MetaManager.instance, cosmeticPresetsField);
					List<List<int>> presetList2 = GetPresetList(MetaManager.instance, colorPresetsField);
					SaveExtendedStoreFromRuntime(MetaManager.instance, presetList, presetList2, GetTargetSlots(), createHistory, reason);
					WriteLog("Extended presets saved. Reason=" + reason);
				}
			}
			catch (Exception ex)
			{
				WriteFailureLog("SaveExtendedPresetsNow / " + reason, ex);
			}
		}

		private static void RegisterCommands(DebugCommandHandler handler)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			if (!IsEnabled() || (Object)(object)handler == (Object)null || commandRegistered)
			{
				return;
			}
			try
			{
				handler.Register(new ChatCommand("cpeinfo", "Shows CosmeticPresetExtender save information", (Action<bool, string[]>)delegate
				{
					ExtendedPresetStore extendedPresetStore = LoadExtendedStore(allowBackupRecovery: true);
					NormalizeStore(extendedPresetStore);
					WriteLog("Rows=" + GetTargetRows() + " Slots=" + GetTargetSlots() + " VanillaSaveSlots=" + 28 + " ExtendedEntries=" + extendedPresetStore.presets.Count + " UpdatedAtUtc=" + extendedPresetStore.updatedAtUtc);
				}, (Func<bool, string, string[], List<string>>)null, (Func<bool>)null, false));
				handler.Register(new ChatCommand("cpebackup", "Saves extended cosmetic presets now", (Action<bool, string[]>)delegate
				{
					SaveExtendedPresetsNow(createHistory: true, "chat_cpebackup");
				}, (Func<bool, string, string[], List<string>>)null, (Func<bool>)null, false));
				handler.Register(new ChatCommand("cperestore", "Restores extended cosmetic presets now", (Action<bool, string[]>)delegate
				{
					RestoreExtendedPresetsFromStoreNow(forceOverwrite: true, "chat_cperestore");
				}, (Func<bool, string, string[], List<string>>)null, (Func<bool>)null, false));
				commandRegistered = true;
				WriteLog("Chat commands registered: /cpeinfo /cpebackup /cperestore");
			}
			catch (Exception ex)
			{
				WriteFailureLog("RegisterCommands", ex);
			}
		}
	}
}