Decompiled source of DataManager v1.1.0

Silksong.DataManager.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Silksong.DataManager.Data;
using Silksong.DataManager.Json;
using TeamCherry.Localization;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Silksong.DataManager")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("DataManager is a Silksong mod that saves and loads data - global as well as save slot-specific - on behalf of other mods.")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+25249b2f92915785fa1818b1f81859f5a4722502")]
[assembly: AssemblyProduct("Silksong.DataManager")]
[assembly: AssemblyTitle("DataManager")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/silksong-modding/Silksong.DataManager")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Silksong.DataManager
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("org.silksong-modding.datamanager", "DataManager", "1.1.0")]
	public class DataManagerPlugin : BaseUnityPlugin, IOnceSaveDataMod<DMOnceSaveData>, IOnceSaveDataMod
	{
		internal Dictionary<string, ManagedMod> ManagedMods = new Dictionary<string, ManagedMod>();

		public const string Id = "org.silksong-modding.datamanager";

		internal static DataManagerPlugin Instance { get; private set; }

		internal static ManualLogSource InstanceLogger => ((BaseUnityPlugin)Instance).Logger;

		internal ManagedMod ManagedSelf => ManagedMods[((BaseUnityPlugin)this).Info.Metadata.GUID];

		internal DMOnceSaveData? OnceSaveData { get; set; }

		DMOnceSaveData? IOnceSaveDataMod<DMOnceSaveData>.OnceSaveData
		{
			get
			{
				return OnceSaveData;
			}
			set
			{
				OnceSaveData = value;
			}
		}

		public static string Name => "DataManager";

		public static string Version => "1.1.0";

		private void Awake()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			new Harmony("org.silksong-modding.datamanager").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Mod Loaded");
		}

		private void Start()
		{
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				pluginInfo.Deconstruct(out var key, out var value);
				string key2 = key;
				PluginInfo obj = value;
				BaseUnityPlugin val = ((obj != null) ? obj.Instance : null);
				if (val != null && ManagedMod.TryCreate(val, out ManagedMod instance))
				{
					instance.LoadProfileData();
					instance.LoadGlobalData();
					ManagedMods.Add(key2, instance);
				}
			}
		}

		internal static void ClearModdedSaveSlot(int saveSlot)
		{
			string path = DataPaths.SaveSlotDir(saveSlot);
			try
			{
				Directory.Delete(path, recursive: true);
				InstanceLogger.LogInfo((object)$"Cleared modded save slot for slot {saveSlot}");
			}
			catch (DirectoryNotFoundException)
			{
				InstanceLogger.LogInfo((object)$"No modded save slot to clear for slot {saveSlot}");
			}
			catch (Exception arg)
			{
				InstanceLogger.LogError((object)$"Error clearing modded save slot for slot {saveSlot}: {arg}");
			}
		}

		internal static LocalisedString SetSaveIncompatibleText(SaveSlotButton button, LocalisedString s)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			AutoLocalizeTextUI component = ((Component)((Component)button.saveIncompatibleText).gameObject.transform.Find("Small Desc")).gameObject.GetComponent<AutoLocalizeTextUI>();
			LocalisedString text = component.Text;
			component.Text = s;
			return text;
		}

		internal List<string> MissingMods(int saveSlot)
		{
			try
			{
				ManagedSelf.LoadOnceSaveData(saveSlot);
			}
			catch (IOException)
			{
				return new List<string>();
			}
			return (OnceSaveData?.RequiredModGuids ?? new List<string>()).Where((string guid) => !ManagedMods.ContainsKey(guid)).ToList();
		}
	}
	public static class DataPaths
	{
		public static string ProfileDataDir => Paths.ConfigPath;

		public static string GlobalDataDir => ModdedDir("Global");

		private static string ModdedDir(string subdir)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return Path.Combine(((DesktopPlatform)Platform.Current).saveDirPath, "Modded", subdir);
		}

		internal static string SaveSlotDir(int saveSlot)
		{
			return ModdedDir($"user{saveSlot}");
		}

		public static string SaveDataDir(int saveSlot)
		{
			return Path.Combine(SaveSlotDir(saveSlot), "SaveData");
		}

		public static string OnceSaveDataDir(int saveSlot)
		{
			return Path.Combine(SaveSlotDir(saveSlot), "OncePerSave");
		}
	}
	[HarmonyPatch(typeof(GameManager), "OnApplicationQuit")]
	internal static class OnQuitGameHook
	{
		private static void Postfix()
		{
			Directory.CreateDirectory(DataPaths.ProfileDataDir);
			Directory.CreateDirectory(DataPaths.GlobalDataDir);
			foreach (ManagedMod value in DataManagerPlugin.Instance.ManagedMods.Values)
			{
				value.SaveProfileData();
				value.SaveGlobalData();
			}
		}
	}
	[HarmonyPatch(typeof(GameManager), "SetLoadedGameData", new Type[]
	{
		typeof(SaveGameData),
		typeof(int)
	})]
	internal static class SaveDataLoadHook
	{
		private static void Postfix(int saveSlot)
		{
			Dictionary<string, ManagedMod>.ValueCollection values = DataManagerPlugin.Instance.ManagedMods.Values;
			if (saveSlot == 0)
			{
				foreach (ManagedMod item in values)
				{
					ISaveDataMod saveData = item.SaveData;
					if (saveData != null)
					{
						saveData.UntypedSaveData = null;
					}
					IOnceSaveDataMod onceSaveData = item.OnceSaveData;
					if (onceSaveData != null)
					{
						onceSaveData.UntypedOnceSaveData = null;
					}
				}
				return;
			}
			foreach (ManagedMod item2 in values)
			{
				item2.LoadOnceSaveData(saveSlot);
				item2.LoadSaveData(saveSlot);
			}
		}
	}
	[HarmonyPatch(typeof(GameManager), "SaveGame", new Type[]
	{
		typeof(int),
		typeof(Action<bool>),
		typeof(bool),
		typeof(AutoSaveName)
	})]
	internal static class SaveDataSaveHook
	{
		private static void Prefix(int saveSlot, ref Action<bool> ogCallback)
		{
			if (saveSlot == 0)
			{
				return;
			}
			Action<bool> ogCallbackCopy = ogCallback;
			ogCallback = delegate(bool didSave)
			{
				ogCallbackCopy?.Invoke(didSave);
				if (!didSave)
				{
					return;
				}
				Directory.CreateDirectory(DataPaths.SaveDataDir(saveSlot));
				foreach (ManagedMod value in DataManagerPlugin.Instance.ManagedMods.Values)
				{
					value.SaveSaveData(saveSlot);
				}
			};
		}
	}
	[HarmonyPatch(typeof(GameManager), "StartNewGame")]
	internal static class OnceSetupHook
	{
		private static void Postfix(GameManager __instance)
		{
			int profileID = __instance.profileID;
			if (profileID == 0)
			{
				return;
			}
			Dictionary<string, ManagedMod>.ValueCollection values = DataManagerPlugin.Instance.ManagedMods.Values;
			string path = DataPaths.OnceSaveDataDir(profileID);
			DataManagerPlugin.ClearModdedSaveSlot(profileID);
			Directory.CreateDirectory(path);
			List<string> requiredModGuids = (from x in values
				where x.IsRequired
				select x.Guid).ToList();
			DataManagerPlugin.Instance.OnceSaveData = new DMOnceSaveData
			{
				RequiredModGuids = requiredModGuids
			};
			foreach (ManagedMod item in values)
			{
				item.SaveOnceSaveData(profileID);
			}
		}
	}
	[HarmonyPatch(typeof(GameManager), "ClearSaveFile")]
	internal static class SaveDataClearHook
	{
		private static void Postfix(int saveSlot)
		{
			if (saveSlot != 0)
			{
				DataManagerPlugin.ClearModdedSaveSlot(saveSlot);
			}
		}
	}
	[HarmonyPatch(typeof(SaveSlotButton), "ProcessSaveStats")]
	internal static class ValidationHook
	{
		private static LocalisedString? vanillaSaveIncompatibleText;

		private static bool Prefix(SaveSlotButton __instance, ref bool __result, bool doAnimate, string errorInfo)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			int saveSlotIndex = __instance.SaveSlotIndex;
			List<string> list = DataManagerPlugin.Instance.MissingMods(saveSlotIndex);
			if (list.Count == 0)
			{
				LocalisedString? val = vanillaSaveIncompatibleText;
				if (val.HasValue)
				{
					LocalisedString valueOrDefault = val.GetValueOrDefault();
					DataManagerPlugin.SetSaveIncompatibleText(__instance, valueOrDefault);
					vanillaSaveIncompatibleText = null;
				}
				return true;
			}
			DataManagerPlugin.InstanceLogger.LogInfo((object)$"save slot {saveSlotIndex} has save data for missing mods:");
			foreach (string item in list)
			{
				DataManagerPlugin.InstanceLogger.LogInfo((object)item);
			}
			vanillaSaveIncompatibleText = DataManagerPlugin.SetSaveIncompatibleText(__instance, new LocalisedString("Mods.org.silksong-modding.datamanager", "REQUIRED_MODS_MISSING"));
			CheatManager.LastErrorText = errorInfo;
			__instance.ChangeSaveFileState((SaveFileStates)5, doAnimate);
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(SaveSlotButton), "OverrideSaveData")]
	internal static class OverrideSaveDataHook
	{
		private static void Postfix(SaveSlotButton __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)__instance.State != 10)
			{
				return;
			}
			int saveSlotIndex = __instance.SaveSlotIndex;
			string path = DataPaths.SaveDataDir(saveSlotIndex);
			try
			{
				Directory.Delete(path, recursive: true);
			}
			catch (Exception arg)
			{
				DataManagerPlugin.InstanceLogger.LogError((object)$"Error overring save data for slot {saveSlotIndex}: {arg}");
			}
		}
	}
	public interface IGlobalDataMod<T> : IGlobalDataMod where T : class
	{
		T? GlobalData { get; set; }

		Type IGlobalDataMod.GlobalDataType => typeof(T);

		object? IGlobalDataMod.UntypedGlobalData
		{
			get
			{
				return GlobalData;
			}
			set
			{
				GlobalData = ((value == null) ? null : ((T)value));
			}
		}
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	public interface IGlobalDataMod
	{
		Type GlobalDataType { get; }

		object? UntypedGlobalData { get; set; }
	}
	public interface IOnceSaveDataMod<T> : IOnceSaveDataMod where T : class
	{
		T? OnceSaveData { get; set; }

		Type IOnceSaveDataMod.OnceSaveDataType => typeof(T);

		object? IOnceSaveDataMod.UntypedOnceSaveData
		{
			get
			{
				return OnceSaveData;
			}
			set
			{
				OnceSaveData = ((value == null) ? null : ((T)value));
			}
		}
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	public interface IOnceSaveDataMod
	{
		Type OnceSaveDataType { get; }

		object? UntypedOnceSaveData { get; set; }
	}
	public interface IProfileDataMod<T> : IProfileDataMod where T : class
	{
		T? ProfileData { get; set; }

		Type IProfileDataMod.ProfileDataType => typeof(T);

		object? IProfileDataMod.UntypedProfileData
		{
			get
			{
				return ProfileData;
			}
			set
			{
				ProfileData = ((value == null) ? null : ((T)value));
			}
		}
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	public interface IProfileDataMod
	{
		Type ProfileDataType { get; }

		object? UntypedProfileData { get; set; }
	}
	public interface IRequiredMod
	{
		bool IsRequired { get; }
	}
	public interface ISaveDataMod<T> : ISaveDataMod where T : class
	{
		T? SaveData { get; set; }

		Type ISaveDataMod.SaveDataType => typeof(T);

		object? ISaveDataMod.UntypedSaveData
		{
			get
			{
				return SaveData;
			}
			set
			{
				SaveData = ((value == null) ? null : ((T)value));
			}
		}
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	public interface ISaveDataMod
	{
		Type SaveDataType { get; }

		object? UntypedSaveData { get; set; }
	}
	internal record ManagedMod(string Guid, IProfileDataMod? ProfileData, IGlobalDataMod? GlobalData, ISaveDataMod? SaveData, IOnceSaveDataMod? OnceSaveData, IRequiredMod? RequiredMod)
	{
		public bool HasAnyGlobalData
		{
			get
			{
				if (ProfileData == null)
				{
					return GlobalData != null;
				}
				return true;
			}
		}

		public bool HasAnySaveData
		{
			get
			{
				if (SaveData == null)
				{
					return OnceSaveData != null;
				}
				return true;
			}
		}

		public bool IsRequired => RequiredMod?.IsRequired ?? false;

		private string ProfileDataPath => Path.Combine(DataPaths.ProfileDataDir, Guid + ".json");

		private string GlobalDataPath => Path.Combine(DataPaths.GlobalDataDir, Guid + ".json.dat");

		internal static bool TryCreate(BaseUnityPlugin plugin, [NotNullWhen(true)] out ManagedMod? instance)
		{
			instance = null;
			string gUID = plugin.Info.Metadata.GUID;
			IProfileDataMod profileDataMod = plugin as IProfileDataMod;
			IGlobalDataMod globalDataMod = plugin as IGlobalDataMod;
			ISaveDataMod saveDataMod = plugin as ISaveDataMod;
			IOnceSaveDataMod onceSaveDataMod = plugin as IOnceSaveDataMod;
			IRequiredMod requiredMod = plugin as IRequiredMod;
			if (profileDataMod == null && globalDataMod == null && saveDataMod == null && onceSaveDataMod == null && requiredMod == null)
			{
				return false;
			}
			instance = new ManagedMod(gUID, profileDataMod, globalDataMod, saveDataMod, onceSaveDataMod, requiredMod);
			DataManagerPlugin.InstanceLogger.LogInfo((object)(gUID + " uses data manager"));
			return true;
		}

		internal void LoadProfileData()
		{
			if (ProfileData != null)
			{
				LoadUntypedData(ProfileDataPath, ProfileData.ProfileDataType, delegate(object? obj)
				{
					ProfileData.UntypedProfileData = obj;
				});
			}
		}

		internal void SaveProfileData()
		{
			if (ProfileData != null)
			{
				SaveUntypedData(ProfileDataPath, ProfileData.ProfileDataType, ProfileData.UntypedProfileData);
			}
		}

		internal void LoadGlobalData()
		{
			if (GlobalData != null)
			{
				LoadUntypedData(GlobalDataPath, GlobalData.GlobalDataType, delegate(object? obj)
				{
					GlobalData.UntypedGlobalData = obj;
				});
			}
		}

		internal void SaveGlobalData()
		{
			if (GlobalData != null)
			{
				SaveUntypedData(GlobalDataPath, GlobalData.GlobalDataType, GlobalData.UntypedGlobalData);
			}
		}

		internal void LoadSaveData(int saveSlot)
		{
			if (SaveData != null)
			{
				LoadUntypedData(SaveDataPath(saveSlot), SaveData.SaveDataType, delegate(object? obj)
				{
					SaveData.UntypedSaveData = obj;
				});
			}
		}

		internal void SaveSaveData(int saveSlot)
		{
			if (SaveData != null)
			{
				SaveUntypedData(SaveDataPath(saveSlot), SaveData.SaveDataType, SaveData.UntypedSaveData);
			}
		}

		internal void LoadOnceSaveData(int saveSlot)
		{
			if (OnceSaveData != null)
			{
				LoadUntypedData(OnceSaveDataPath(saveSlot), OnceSaveData.OnceSaveDataType, delegate(object? obj)
				{
					OnceSaveData.UntypedOnceSaveData = obj;
				});
			}
		}

		internal void SaveOnceSaveData(int saveSlot)
		{
			if (OnceSaveData != null)
			{
				SaveUntypedData(OnceSaveDataPath(saveSlot), OnceSaveData.OnceSaveDataType, OnceSaveData.UntypedOnceSaveData);
			}
		}

		private string SaveDataPath(int slot)
		{
			return Path.Combine(DataPaths.SaveDataDir(slot), Guid + ".json.dat");
		}

		private string OnceSaveDataPath(int slot)
		{
			return Path.Combine(DataPaths.OnceSaveDataDir(slot), Guid + ".json.dat");
		}

		private void LoadUntypedData(string path, Type dataType, Action<object?> onLoad)
		{
			try
			{
				object obj = JsonUtil.Deserialize(path, dataType);
				onLoad(obj);
				DataManagerPlugin.InstanceLogger.LogInfo((object)("Loaded " + dataType.Name + " for mod " + Guid));
			}
			catch (Exception ex) when (((ex is FileNotFoundException || ex is DirectoryNotFoundException) ? 1 : 0) != 0)
			{
				onLoad(null);
			}
			catch (Exception arg)
			{
				onLoad(null);
				DataManagerPlugin.InstanceLogger.LogError((object)$"Error loading {dataType.Name} for mod {Guid}: {arg}");
			}
		}

		private void SaveUntypedData(string path, Type dataType, object? untypedData)
		{
			if (untypedData == null)
			{
				return;
			}
			try
			{
				JsonUtil.Serialize(path, untypedData);
				DataManagerPlugin.InstanceLogger.LogInfo((object)("Saved " + dataType.Name + " for mod " + Guid));
			}
			catch (Exception arg)
			{
				DataManagerPlugin.InstanceLogger.LogError((object)$"Error saving {dataType.Name} for mod {Guid}: {arg}");
			}
		}

		[CompilerGenerated]
		protected virtual bool PrintMembers(StringBuilder builder)
		{
			RuntimeHelpers.EnsureSufficientExecutionStack();
			builder.Append("Guid = ");
			builder.Append((object?)Guid);
			builder.Append(", ProfileData = ");
			builder.Append(ProfileData);
			builder.Append(", GlobalData = ");
			builder.Append(GlobalData);
			builder.Append(", SaveData = ");
			builder.Append(SaveData);
			builder.Append(", OnceSaveData = ");
			builder.Append(OnceSaveData);
			builder.Append(", RequiredMod = ");
			builder.Append(RequiredMod);
			builder.Append(", HasAnyGlobalData = ");
			builder.Append(HasAnyGlobalData.ToString());
			builder.Append(", HasAnySaveData = ");
			builder.Append(HasAnySaveData.ToString());
			builder.Append(", IsRequired = ");
			builder.Append(IsRequired.ToString());
			return true;
		}
	}
}
namespace Silksong.DataManager.Json
{
	internal static class JsonUtil
	{
		private static readonly JsonSerializerSettings _settings = new JsonSerializerSettings
		{
			TypeNameHandling = (TypeNameHandling)4,
			ObjectCreationHandling = (ObjectCreationHandling)2
		};

		internal static object? Deserialize(string path, Type type)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			using StreamReader streamReader = File.OpenText(path);
			JsonTextReader val = new JsonTextReader((TextReader)streamReader);
			try
			{
				return JsonSerializer.CreateDefault(_settings).Deserialize((JsonReader)(object)val, type);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		internal static void Serialize(string path, object value)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			using StreamWriter streamWriter = File.CreateText(path);
			JsonTextWriter val = new JsonTextWriter((TextWriter)streamWriter);
			try
			{
				JsonSerializer.CreateDefault(_settings).Serialize((JsonWriter)(object)val, value);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
	}
}
namespace Silksong.DataManager.Data
{
	internal class DMOnceSaveData
	{
		public List<string> RequiredModGuids = new List<string>();
	}
}