Decompiled source of SketchbookPlus v1.3.1

Mods/SketchbookPlus.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppRUMBLE.Managers;
using Il2CppRUMBLE.Players;
using Il2CppRUMBLE.Utilities;
using MelonLoader;
using MelonLoader.Preferences;
using RumbleModdingAPI.RMAPI;
using SketchbookPlus;
using UIFramework;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(main), "SketchbookPlus", "1.3.1", "UlvakSkillz", null)]
[assembly: MelonGame("Buckethead Entertainment", "RUMBLE")]
[assembly: MelonColor(255, 195, 0, 255)]
[assembly: MelonAuthorColor(255, 195, 0, 255)]
[assembly: VerifyLoaderVersion(0, 6, 6, true)]
[assembly: MelonAdditionalDependencies(new string[] { "UIFramework" })]
[assembly: AssemblyDescription("")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3b03f008-9dbb-4382-a110-b59ee8b632ca")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SketchbookPlus")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f862b9cde5a452b3962bff9868f09b89b6c13811")]
[assembly: AssemblyProduct("SketchbookPlus")]
[assembly: AssemblyTitle("SketchbookPlus")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SketchbookPlus;

public static class BuildInfo
{
	public const string ModName = "SketchbookPlus";

	public const string ModVersion = "1.3.1";

	public const string Author = "UlvakSkillz";
}
public class main : MelonMod
{
	[CompilerGenerated]
	private sealed class <checkPlayer>d__17 : IEnumerator<object>, IEnumerator, IDisposable
	{
		private int <>1__state;

		private object <>2__current;

		public Player player;

		public main <>4__this;

		private string <visuals>5__1;

		private string <name>5__2;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <checkPlayer>d__17(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<visuals>5__1 = null;
			<name>5__2 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>4__this.debugLog("Storing Player");
				<>2__current = (object)new WaitForSeconds(1f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<visuals>5__1 = <>4__this.getOutfitString(player.Data.VisualData);
				<name>5__2 = player.Data.GeneralData.PublicUsername;
				if (<name>5__2.Contains("<") || <name>5__2.Contains(">") || <name>5__2.Contains(":"))
				{
					<name>5__2 = <name>5__2.Replace("<", "_");
					<name>5__2 = <name>5__2.Replace(">", "_");
					<name>5__2 = <name>5__2.Replace(":", "_");
				}
				if (!File.Exists("UserData\\SketchbookPlus\\Stored\\" + <name>5__2 + ".txt"))
				{
					<>4__this.debugLog("Saving " + <name>5__2 + "'s Model");
				}
				else
				{
					<>4__this.debugLog("Found Existing " + <name>5__2 + "'s Model, Overriding Text");
				}
				<>4__this.saveFile(<visuals>5__1, "UserData\\SketchbookPlus\\Stored\\" + <name>5__2 + ".txt");
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private Random random = new Random(DateTime.Now.Millisecond * DateTime.Now.Second * DateTime.Now.Minute);

	private List<string> acceptedFiles = new List<string>();

	private List<string> failedFiles = new List<string>();

	private List<string> pendingFiles = new List<string>();

	private List<string> acceptedFilesTexts = new List<string>();

	private List<string> pendingFilesTexts = new List<string>();

	private List<List<int>> acceptedItems = new List<List<int>>();

	private bool randomizerInit = false;

	private int lastOutfit = -1;

	private void Log(string msg)
	{
		MelonLogger.Msg(msg);
	}

	private void debugLog(string msg)
	{
		if (Preferences.PrefDebugging.Value)
		{
			MelonLogger.Msg("-" + msg);
		}
	}

	public override void OnLateInitializeMelon()
	{
		if (!Directory.Exists("UserData\\SketchbookPlus"))
		{
			Directory.CreateDirectory("UserData\\SketchbookPlus");
		}
		if (!Directory.Exists("UserData\\SketchbookPlus\\Stored"))
		{
			Directory.CreateDirectory("UserData\\SketchbookPlus\\Stored");
		}
		if (!File.Exists("UserData\\SketchbookPlus\\BlackListedItems.txt"))
		{
			saveFile("", "UserData\\SketchbookPlus\\BlackListedItems.txt", addAcceptedFile: false);
		}
		Actions.onMapInitialized += mapInit;
		Actions.onPlayerSpawned += playerJoined;
		pendingFiles.Clear();
		acceptedFiles.Clear();
		failedFiles.Clear();
	}

	public override void OnInitializeMelon()
	{
		Preferences.InitPrefs();
		((ModelModItem)UI.Register((MelonBase)(object)this, (MelonPreferences_Category[])(object)new MelonPreferences_Category[3]
		{
			Preferences.SketchbookPlusCategory,
			Preferences.SaveLoadCategory,
			Preferences.RandomizerCategory
		})).OnModSaved += Save;
	}

	private void Save()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Expected O, but got Unknown
		debugLog("Main Method Running");
		PlayerVisualData visualData = Singleton<PlayerManager>.instance.localPlayer.Data.VisualData;
		PlayerVisualData val = new PlayerVisualData(visualData);
		int[] array = new int[acceptedItems.Count];
		if (Preferences.PrefUpdateFilesTexts.Value)
		{
			debugLog("Clearing Known Files");
			((MelonPreferences_Entry)Preferences.PrefUpdateFilesTexts).ResetToDefault();
			pendingFiles.Clear();
			acceptedFiles.Clear();
			failedFiles.Clear();
		}
		debugLog("Rechecking Files");
		recheckFiles();
		debugLog("Done Rechecking Files");
		if (!Preferences.PrefSavedOutfitName.Value.ToLower().EndsWith(".txt"))
		{
			MelonPreferences_Entry<string> prefSavedOutfitName = Preferences.PrefSavedOutfitName;
			prefSavedOutfitName.Value += ".txt";
		}
		if (!Preferences.PrefOutfitNameToLoad.Value.ToLower().EndsWith(".txt"))
		{
			MelonPreferences_Entry<string> prefOutfitNameToLoad = Preferences.PrefOutfitNameToLoad;
			prefOutfitNameToLoad.Value += ".txt";
		}
		if (Preferences.PrefOutfitTypeToLoad.Value == OutfitTypes.RandomizerOutfit)
		{
			debugLog("Starting Randomizer");
			string[] array2 = getOutfitString(visualData).Split(",");
			debugLog("Got Original Outfit");
			int[] array3 = new int[20]
			{
				0, 1, 2, 28, 29, 30, 31, 32, 33, 34,
				35, 36, 37, 58, 59, 60, 61, 62, 63, 64
			};
			int[] array4 = new int[6] { 3, 4, 5, 6, 7, 8 };
			int[] array5 = new int[30]
			{
				9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
				38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
				48, 49, 50, 51, 52, 53, 54, 55, 56, 57
			};
			int[] array6 = new int[9] { 19, 20, 21, 22, 23, 24, 25, 26, 27 };
			string[] array7 = new string[array3.Length + array4.Length + array5.Length + array6.Length];
			debugLog("Set PVD Variable Spots");
			for (int i = 0; i < array2.Length; i++)
			{
				array7[i] = array2[i];
			}
			debugLog("Updated New PVD Variables");
			for (int j = 0; j < array3.Length + array4.Length + array5.Length + array6.Length; j++)
			{
				if ((Preferences.PrefRandomizerIdentity.Value && array3.Contains(j)) || (Preferences.PrefRandomizerArmorColors.Value && array4.Contains(j)) || (Preferences.PrefArmorItems.Value && array6.Contains(j)) || (Preferences.PrefRandomizerMarkings.Value && array5.Contains(j)))
				{
					array7[j] = acceptedItems[j][random.Next(0, acceptedItems[j].Count)].ToString();
				}
			}
			debugLog("Outfit Ready to Set");
			setPVD(visualData, array7);
			Log("Randomizer Outfit Set: " + getOutfitString(visualData));
		}
		else if (Preferences.PrefSaveOutfit.Value)
		{
			((MelonPreferences_Entry)Preferences.PrefSaveOutfit).ResetToDefault();
			debugLog("Saving Outfit: UserData\\SketchbookPlus\\" + Preferences.PrefSavedOutfitName.Value);
			string outfitString = getOutfitString(Singleton<PlayerManager>.instance.localPlayer.Data.VisualData);
			debugLog("File Text: " + outfitString);
			saveFile(outfitString, "UserData\\SketchbookPlus\\" + Preferences.PrefSavedOutfitName.Value);
		}
		else
		{
			if (!(Scene.GetSceneName() == "Gym"))
			{
				return;
			}
			if (Preferences.PrefOutfitTypeToLoad.Value == OutfitTypes.RandomFromFilesOutfit && acceptedFiles.Count > 0)
			{
				int num = random.Next(0, acceptedFiles.Count);
				while (num == lastOutfit && acceptedFiles.Count > 1)
				{
					num = random.Next(0, acceptedFiles.Count);
				}
				debugLog("Loading Random: " + acceptedFiles[num]);
				loadOutfit(acceptedFiles[num]);
				lastOutfit = num;
			}
			else if (Preferences.PrefOutfitTypeToLoad.Value == OutfitTypes.SavedOutfit)
			{
				debugLog("Loading Selected: " + Preferences.PrefOutfitNameToLoad.Value);
				loadOutfit("UserData\\SketchbookPlus\\" + Preferences.PrefOutfitNameToLoad.Value);
			}
		}
	}

	private void recheckFiles()
	{
		string[] files = Directory.GetFiles("UserData\\SketchbookPlus");
		string[] array = files;
		foreach (string text in array)
		{
			if (!(text == "UserData\\SketchbookPlus\\config.cfg") && !(text == "UserData\\SketchbookPlus\\BlackListedItems.txt") && !failedFiles.Contains(text) && !acceptedFiles.Contains(text))
			{
				debugLog("Pending File: " + text);
				pendingFiles.Add(text);
			}
		}
		loadFileTexts();
		while (pendingFiles.Count > 0)
		{
			if (!CheckFileValidity(pendingFiles[0]))
			{
				Log("Removing Bad File: " + pendingFiles[0]);
				Log("Removing Bad File's Text: " + pendingFilesTexts[0]);
				failedFiles.Add(pendingFiles[0]);
				pendingFiles.Remove(pendingFiles[0]);
				pendingFilesTexts.RemoveAt(0);
			}
			else
			{
				debugLog("Accepting file: " + pendingFiles[0]);
				acceptedFiles.Add(pendingFiles[0]);
				acceptedFilesTexts.Add(pendingFilesTexts[0]);
				pendingFiles.Remove(pendingFiles[0]);
				pendingFilesTexts.RemoveAt(0);
			}
		}
	}

	private void saveFile(string textToSave, string file, bool addAcceptedFile = true)
	{
		if (!File.Exists(file))
		{
			acceptedFiles.Add(file);
		}
		FileStream fileStream = File.Create(file);
		byte[] bytes = Encoding.UTF8.GetBytes(textToSave);
		fileStream.Write(bytes);
		fileStream.Close();
		fileStream.Dispose();
		Log("Saving " + file + " Complete");
	}

	private void playerJoined(Player player)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Invalid comparison between Unknown and I4
		if (Preferences.PrefStoreOthersOutfits.Value && (int)player.Controller.controllerType == 2)
		{
			MelonCoroutines.Start(checkPlayer(player));
		}
	}

	[IteratorStateMachine(typeof(<checkPlayer>d__17))]
	private IEnumerator checkPlayer(Player player)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <checkPlayer>d__17(0)
		{
			<>4__this = this,
			player = player
		};
	}

	private void setupRandomizer()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		debugLog("Setting Up Randomizer");
		int num = 50;
		PlayerVisualData visualData = Singleton<PlayerManager>.instance.localPlayer.Data.VisualData;
		PlayerVisualData val = new PlayerVisualData(visualData);
		setPVD(val, visualData);
		string outfitString = getOutfitString(visualData);
		string[] array = outfitString.Split(",");
		int[] array2 = new int[array.Length];
		for (int i = 0; i < array.Length; i++)
		{
			array2[i] = int.Parse(array[i]);
		}
		for (int j = 0; j < array.Length; j++)
		{
			List<int> list = new List<int>();
			string text = "Spot " + j + ": ";
			for (int k = 0; k <= num; k++)
			{
				array2[j] = k;
				string[] array3 = new string[array2.Length];
				for (int l = 0; l < array3.Length; l++)
				{
					array3[l] = array2[l].ToString();
				}
				setPVD(val, array3);
				if (checkItems(val.ToPlayfabDataString(), isSilent: true))
				{
					list.Add(k);
					text = text + k + ", ";
				}
			}
			acceptedItems.Add(list);
			debugLog(text);
			for (int m = 0; m < array.Length; m++)
			{
				array2[m] = int.Parse(array[m]);
			}
		}
		setupBlackList();
		debugLog("Randomizer Setup");
		randomizerInit = true;
	}

	private void setupBlackList()
	{
		string[] array = File.ReadAllLines("UserData\\SketchbookPlus\\BlackListedItems.txt");
		try
		{
			string[] array2 = array;
			foreach (string text in array2)
			{
				string[] array3 = text.Split(",");
				if (acceptedItems[int.Parse(array3[0])].Remove(int.Parse(array3[1])))
				{
					Log("Removed Item: " + text);
				}
			}
		}
		catch
		{
			MelonLogger.Error("Error Reading BlackList File");
		}
	}

	private string getOutfitString(PlayerVisualData pvd)
	{
		string text = "";
		for (int i = 0; i < ((Il2CppArrayBase<short>)(object)pvd.ColorationIndexes).Count; i++)
		{
			text = text + ((Il2CppArrayBase<short>)(object)pvd.ColorationIndexes)[i] + ",";
		}
		for (int j = 0; j < ((Il2CppArrayBase<short>)(object)pvd.CustomizationPartIndexes).Count; j++)
		{
			text = text + ((Il2CppArrayBase<short>)(object)pvd.CustomizationPartIndexes)[j] + ",";
		}
		for (int k = 0; k < ((Il2CppArrayBase<short>)(object)pvd.OtherCustomizationIndexes).Count; k++)
		{
			text = text + ((Il2CppArrayBase<short>)(object)pvd.OtherCustomizationIndexes)[k] + ",";
		}
		for (int l = 0; l < ((Il2CppArrayBase<short>)(object)pvd.TextureCustomizationIndexes).Count; l++)
		{
			text = text + ((Il2CppArrayBase<short>)(object)pvd.TextureCustomizationIndexes)[l] + ",";
		}
		for (int m = 0; m < ((Il2CppArrayBase<short>)(object)pvd.TextureOpacityIndexes).Count; m++)
		{
			text = text + ((Il2CppArrayBase<short>)(object)pvd.TextureOpacityIndexes)[m] + ",";
		}
		for (int n = 0; n < ((Il2CppArrayBase<short>)(object)pvd.WeightAdjustementIndexes).Count; n++)
		{
			text += ((Il2CppArrayBase<short>)(object)pvd.WeightAdjustementIndexes)[n];
			if (n != ((Il2CppArrayBase<short>)(object)pvd.WeightAdjustementIndexes).Count - 1)
			{
				text += ",";
			}
		}
		return text;
	}

	private void loadOutfit(string fileName)
	{
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Expected O, but got Unknown
		if (acceptedFiles.IndexOf(fileName) == -1)
		{
			MelonLogger.Error("Not An Accepted File: " + fileName);
			return;
		}
		Log("Text: " + acceptedFilesTexts[acceptedFiles.IndexOf(fileName)]);
		string[] data = acceptedFilesTexts[acceptedFiles.IndexOf(fileName)].Split(',');
		PlayerVisualData visualData = Singleton<PlayerManager>.instance.localPlayer.Data.VisualData;
		PlayerVisualData val = new PlayerVisualData(visualData);
		setPVD(val, data);
		if (checkItems(val.ToPlayfabDataString()))
		{
			debugLog("Setting PVD Now");
			setPVD(visualData, val);
			Log("Loaded Outfit for Next Scene: " + fileName);
		}
	}

	private bool CheckFileValidity(string fileName)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		string[] data = pendingFilesTexts[pendingFiles.IndexOf(fileName)].Split(',');
		PlayerVisualData val = new PlayerVisualData(Singleton<PlayerManager>.instance.localPlayer.Data.VisualData);
		try
		{
			setPVD(val, data);
		}
		catch
		{
			Log("Invalid File Text");
			return false;
		}
		return checkItems(val.ToPlayfabDataString());
	}

	private void setPVD(PlayerVisualData pvd, string[] data)
	{
		int num = 0;
		for (int i = 0; i < ((Il2CppArrayBase<short>)(object)pvd.ColorationIndexes).Count; i++)
		{
			((Il2CppArrayBase<short>)(object)pvd.ColorationIndexes)[i] = short.Parse(data[num]);
			num++;
		}
		for (int j = 0; j < ((Il2CppArrayBase<short>)(object)pvd.CustomizationPartIndexes).Count; j++)
		{
			((Il2CppArrayBase<short>)(object)pvd.CustomizationPartIndexes)[j] = short.Parse(data[num]);
			num++;
		}
		for (int k = 0; k < ((Il2CppArrayBase<short>)(object)pvd.OtherCustomizationIndexes).Count; k++)
		{
			((Il2CppArrayBase<short>)(object)pvd.OtherCustomizationIndexes)[k] = short.Parse(data[num]);
			num++;
		}
		for (int l = 0; l < ((Il2CppArrayBase<short>)(object)pvd.TextureCustomizationIndexes).Count; l++)
		{
			((Il2CppArrayBase<short>)(object)pvd.TextureCustomizationIndexes)[l] = short.Parse(data[num]);
			num++;
		}
		for (int m = 0; m < ((Il2CppArrayBase<short>)(object)pvd.TextureOpacityIndexes).Count; m++)
		{
			((Il2CppArrayBase<short>)(object)pvd.TextureOpacityIndexes)[m] = short.Parse(data[num]);
			num++;
		}
		for (int n = 0; n < ((Il2CppArrayBase<short>)(object)pvd.WeightAdjustementIndexes).Count; n++)
		{
			((Il2CppArrayBase<short>)(object)pvd.WeightAdjustementIndexes)[n] = short.Parse(data[num]);
			num++;
		}
	}

	private void setPVD(PlayerVisualData pvdTo, PlayerVisualData pvdFrom)
	{
		for (int i = 0; i < ((Il2CppArrayBase<short>)(object)pvdTo.ColorationIndexes).Count; i++)
		{
			((Il2CppArrayBase<short>)(object)pvdTo.ColorationIndexes)[i] = ((Il2CppArrayBase<short>)(object)pvdFrom.ColorationIndexes)[i];
		}
		for (int j = 0; j < ((Il2CppArrayBase<short>)(object)pvdTo.CustomizationPartIndexes).Count; j++)
		{
			((Il2CppArrayBase<short>)(object)pvdTo.CustomizationPartIndexes)[j] = ((Il2CppArrayBase<short>)(object)pvdFrom.CustomizationPartIndexes)[j];
		}
		for (int k = 0; k < ((Il2CppArrayBase<short>)(object)pvdTo.OtherCustomizationIndexes).Count; k++)
		{
			((Il2CppArrayBase<short>)(object)pvdTo.OtherCustomizationIndexes)[k] = ((Il2CppArrayBase<short>)(object)pvdFrom.OtherCustomizationIndexes)[k];
		}
		for (int l = 0; l < ((Il2CppArrayBase<short>)(object)pvdTo.TextureCustomizationIndexes).Count; l++)
		{
			((Il2CppArrayBase<short>)(object)pvdTo.TextureCustomizationIndexes)[l] = ((Il2CppArrayBase<short>)(object)pvdFrom.TextureCustomizationIndexes)[l];
		}
		for (int m = 0; m < ((Il2CppArrayBase<short>)(object)pvdTo.TextureOpacityIndexes).Count; m++)
		{
			((Il2CppArrayBase<short>)(object)pvdTo.TextureOpacityIndexes)[m] = ((Il2CppArrayBase<short>)(object)pvdFrom.TextureOpacityIndexes)[m];
		}
		for (int n = 0; n < ((Il2CppArrayBase<short>)(object)pvdTo.WeightAdjustementIndexes).Count; n++)
		{
			((Il2CppArrayBase<short>)(object)pvdTo.WeightAdjustementIndexes)[n] = ((Il2CppArrayBase<short>)(object)pvdFrom.WeightAdjustementIndexes)[n];
		}
	}

	private bool checkItems(string tempPVDEconomyDataString, bool isSilent = false)
	{
		string[] array = tempPVDEconomyDataString.Split(':');
		bool flag = true;
		for (int i = 0; i < array.Length; i++)
		{
			if (i == 0 || i == 5)
			{
				continue;
			}
			string[] array2 = array[i].Split(",");
			string[] array3 = array2;
			foreach (string text in array3)
			{
				if (!Singleton<PlayerManager>.instance.localPlayer.Data.EconomyData.ReceivedItems.Contains(text))
				{
					flag = false;
					if (!isSilent)
					{
						Log("Item Not Redeemed");
					}
					break;
				}
			}
			if (!flag)
			{
				break;
			}
		}
		if (flag)
		{
			return true;
		}
		return false;
	}

	private void mapInit(string map)
	{
		debugLog("RMAPI triggered MapInit");
		if (map == "Gym")
		{
			debugLog("Map is Gym");
			if (!randomizerInit)
			{
				debugLog("Setting up Randomizer");
				setupRandomizer();
			}
			Save();
		}
	}

	private void loadFileTexts()
	{
		foreach (string pendingFile in pendingFiles)
		{
			string item = File.ReadAllText(pendingFile);
			pendingFilesTexts.Add(item);
		}
	}
}
public enum OutfitTypes
{
	[Display(Name = "None")]
	None,
	[Display(Name = "Outfit From Selected File")]
	SavedOutfit,
	[Display(Name = "Random Outfit From Files")]
	RandomFromFilesOutfit,
	[Display(Name = "Randomizer Outfit")]
	RandomizerOutfit
}
public class Preferences
{
	private const string CONFIG_FILE = "config.cfg";

	private const string USER_DATA = "UserData/SketchbookPlus/";

	internal static Dictionary<MelonPreferences_Entry, object> LastSavedValues = new Dictionary<MelonPreferences_Entry, object>();

	internal static MelonPreferences_Category SketchbookPlusCategory;

	internal static MelonPreferences_Entry<OutfitTypes> PrefOutfitTypeToLoad;

	internal static MelonPreferences_Entry<bool> PrefStoreOthersOutfits;

	internal static MelonPreferences_Entry<bool> PrefUpdateFilesTexts;

	internal static MelonPreferences_Entry<bool> PrefDebugging;

	internal static MelonPreferences_Category SaveLoadCategory;

	internal static MelonPreferences_Entry<bool> PrefSaveOutfit;

	internal static MelonPreferences_Entry<string> PrefSavedOutfitName;

	internal static MelonPreferences_Entry<string> PrefOutfitNameToLoad;

	internal static MelonPreferences_Category RandomizerCategory;

	internal static MelonPreferences_Entry<bool> PrefRandomizerIdentity;

	internal static MelonPreferences_Entry<bool> PrefRandomizerArmorColors;

	internal static MelonPreferences_Entry<bool> PrefArmorItems;

	internal static MelonPreferences_Entry<bool> PrefRandomizerMarkings;

	internal static void InitPrefs()
	{
		if (!Directory.Exists("UserData/SketchbookPlus/"))
		{
			Directory.CreateDirectory("UserData/SketchbookPlus/");
		}
		SketchbookPlusCategory = MelonPreferences.CreateCategory("SketchbookPlus", "Settings");
		SketchbookPlusCategory.SetFilePath(Path.Combine("UserData/SketchbookPlus/", "config.cfg"));
		PrefOutfitTypeToLoad = SketchbookPlusCategory.CreateEntry<OutfitTypes>("OutfitTypeToLoad", OutfitTypes.None, "Outfit Type to Load", "Selects what type of Outfit to Load", false, false, (ValueValidator)null, (string)null);
		PrefStoreOthersOutfits = SketchbookPlusCategory.CreateEntry<bool>("StoreOthersOutfits", false, "Store Others Outfits", "Set to True to Store Other Player's Cosmetics to UserData/SketchBookPlus/Stored", false, false, (ValueValidator)null, (string)null);
		PrefUpdateFilesTexts = SketchbookPlusCategory.CreateEntry<bool>("UpdateFilesTexts", false, "Reload Text Files", "Set to True to refresh the Mod's Data from Files", false, false, (ValueValidator)null, (string)null);
		PrefDebugging = SketchbookPlusCategory.CreateEntry<bool>("Debugging", false, "Enable Debugging Logs", "Set to True to Show Logs", false, false, (ValueValidator)null, (string)null);
		SaveLoadCategory = MelonPreferences.CreateCategory("SaveAndLoad", "Save & Load");
		SaveLoadCategory.SetFilePath(Path.Combine("UserData/SketchbookPlus/", "config.cfg"));
		PrefSaveOutfit = SaveLoadCategory.CreateEntry<bool>("SaveOutfit", false, "Save Outfit", "Set to True and Save to Store the Equipped Outfit", false, false, (ValueValidator)null, (string)null);
		PrefSavedOutfitName = SaveLoadCategory.CreateEntry<string>("SavedOutfitName", "DefaultName", "Saved Outfit Name", "File Name To Save Under", false, false, (ValueValidator)null, (string)null);
		PrefOutfitNameToLoad = SaveLoadCategory.CreateEntry<string>("OutfitNameToLoad", "DefaultName", "Outfit to Load from File", "File Name To Load", false, false, (ValueValidator)null, (string)null);
		RandomizerCategory = MelonPreferences.CreateCategory("Randomizer", "Randomizer");
		RandomizerCategory.SetFilePath(Path.Combine("UserData/SketchbookPlus/", "config.cfg"));
		PrefRandomizerIdentity = RandomizerCategory.CreateEntry<bool>("RandomizerIdentity", false, "Identity", "(Sets in Gym) Sets the Player's Identity to a Randomized Selection", false, false, (ValueValidator)null, (string)null);
		PrefRandomizerArmorColors = RandomizerCategory.CreateEntry<bool>("RandomizerArmorColors", true, "Armor Colors", "(Sets in Gym) Sets the Player's Armor Colors to a Randomized Selection", false, false, (ValueValidator)null, (string)null);
		PrefArmorItems = RandomizerCategory.CreateEntry<bool>("RandomizerArmorItems", false, "Armor Items", "(Sets in Gym) Sets the Player's Armor Items to a Randomized Selection", false, false, (ValueValidator)null, (string)null);
		PrefRandomizerMarkings = RandomizerCategory.CreateEntry<bool>("RandomizerMarkings", false, "Markings", "(Sets in Gym) Sets the Player's Markings to a Randomized Selection", false, false, (ValueValidator)null, (string)null);
		((MelonPreferences_Entry)PrefSaveOutfit).ResetToDefault();
		((MelonPreferences_Entry)PrefUpdateFilesTexts).ResetToDefault();
		StoreLastSavedPrefs();
	}

	internal static void StoreLastSavedPrefs()
	{
		List<MelonPreferences_Entry> list = new List<MelonPreferences_Entry>();
		list.AddRange(SketchbookPlusCategory.Entries);
		list.AddRange(SaveLoadCategory.Entries);
		list.AddRange(RandomizerCategory.Entries);
		foreach (MelonPreferences_Entry item in list)
		{
			LastSavedValues[item] = item.BoxedValue;
		}
	}

	public static bool AnyPrefsChanged()
	{
		foreach (KeyValuePair<MelonPreferences_Entry, object> lastSavedValue in LastSavedValues)
		{
			if (!lastSavedValue.Key.BoxedValue.Equals(lastSavedValue.Value))
			{
				return true;
			}
		}
		return false;
	}

	public static bool IsPrefChanged(MelonPreferences_Entry entry)
	{
		if (LastSavedValues.TryGetValue(entry, out var value))
		{
			return !entry.BoxedValue.Equals(value);
		}
		return false;
	}
}