Decompiled source of DataManager v1.2.1

Silksong.DataManager.dll

Decompiled 2 weeks 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.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1+7552e831eeba93ee570a2f1998c590d79a533d49")]
[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.2.1.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.2.1")]
	public class DataManagerPlugin : BaseUnityPlugin, IOnceSaveDataMod<DMOnceSaveData>, IRawOnceSaveDataMod
	{
		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.2.1";

		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)
			{
				return;
			}
			foreach (ManagedMod item in values)
			{
				item.LoadOnceSaveData(saveSlot);
				item.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}");
			}
		}
	}
	[HarmonyPatch(typeof(GameManager), "ReturnToMainMenu")]
	internal static class SavaDataSetToNullHook
	{
		private static void Prefix(ref Action<bool> callback)
		{
			Action<bool> callbackCopy = callback;
			callback = delegate(bool saveCompleteValue)
			{
				callbackCopy?.Invoke(saveCompleteValue);
				DataManagerPlugin.InstanceLogger.LogInfo((object)"Setting mods SaveData to null");
				foreach (ManagedMod value in DataManagerPlugin.Instance.ManagedMods.Values)
				{
					value.SaveData?.ReadSaveData(null);
					value.OnceSaveData?.ReadOnceSaveData(null);
				}
			};
		}
	}
	public interface IGlobalDataMod<T> : IRawGlobalDataMod where T : class
	{
		T? GlobalData { get; set; }

		bool IRawGlobalDataMod.HasGlobalData => GlobalData != null;

		void IRawGlobalDataMod.WriteGlobalData(Stream saveFile)
		{
			using StreamWriter s = new StreamWriter(saveFile);
			JsonUtil.Serialize(s, GlobalData);
		}

		void IRawGlobalDataMod.ReadGlobalData(Stream? saveFile)
		{
			if (saveFile == null)
			{
				GlobalData = null;
				return;
			}
			using StreamReader s = new StreamReader(saveFile);
			GlobalData = JsonUtil.Deserialize<T>(s);
		}
	}
	internal interface IGlobalDataMod
	{
	}
	public interface IOnceSaveDataMod<T> : IRawOnceSaveDataMod where T : class
	{
		T? OnceSaveData { get; set; }

		bool IRawOnceSaveDataMod.HasOnceSaveData => OnceSaveData != null;

		void IRawOnceSaveDataMod.WriteOnceSaveData(Stream saveFile)
		{
			using StreamWriter s = new StreamWriter(saveFile);
			JsonUtil.Serialize(s, OnceSaveData);
		}

		void IRawOnceSaveDataMod.ReadOnceSaveData(Stream? saveFile)
		{
			if (saveFile == null)
			{
				OnceSaveData = null;
				return;
			}
			using StreamReader s = new StreamReader(saveFile);
			OnceSaveData = JsonUtil.Deserialize<T>(s);
		}
	}
	internal interface IOnceSaveDataMod
	{
	}
	public interface IProfileDataMod<T> : IRawProfileDataMod where T : class
	{
		T? ProfileData { get; set; }

		bool IRawProfileDataMod.HasProfileData => ProfileData != null;

		void IRawProfileDataMod.WriteProfileData(Stream saveFile)
		{
			using StreamWriter s = new StreamWriter(saveFile);
			JsonUtil.Serialize(s, ProfileData);
		}

		void IRawProfileDataMod.ReadProfileData(Stream? saveFile)
		{
			if (saveFile == null)
			{
				ProfileData = null;
				return;
			}
			using StreamReader s = new StreamReader(saveFile);
			ProfileData = JsonUtil.Deserialize<T>(s);
		}
	}
	internal interface IProfileDataMod
	{
	}
	public interface IRawGlobalDataMod
	{
		bool HasGlobalData { get; }

		void WriteGlobalData(Stream saveFile);

		void ReadGlobalData(Stream? saveFile);
	}
	public interface IRawOnceSaveDataMod
	{
		bool HasOnceSaveData { get; }

		void WriteOnceSaveData(Stream saveFile);

		void ReadOnceSaveData(Stream? saveFile);
	}
	public interface IRawProfileDataMod
	{
		bool HasProfileData { get; }

		void WriteProfileData(Stream saveFile);

		void ReadProfileData(Stream? saveFile);
	}
	public interface IRawSaveDataMod
	{
		bool HasSaveData { get; }

		void WriteSaveData(Stream saveFile);

		void ReadSaveData(Stream? saveFile);
	}
	public interface IRequiredMod
	{
		bool IsRequired { get; }
	}
	public interface ISaveDataMod<T> : IRawSaveDataMod where T : class
	{
		T? SaveData { get; set; }

		bool IRawSaveDataMod.HasSaveData => SaveData != null;

		void IRawSaveDataMod.WriteSaveData(Stream saveFile)
		{
			using StreamWriter s = new StreamWriter(saveFile);
			JsonUtil.Serialize(s, SaveData);
		}

		void IRawSaveDataMod.ReadSaveData(Stream? saveFile)
		{
			if (saveFile == null)
			{
				SaveData = null;
				return;
			}
			using StreamReader s = new StreamReader(saveFile);
			SaveData = JsonUtil.Deserialize<T>(s);
		}
	}
	internal interface ISaveDataMod
	{
	}
	internal record ManagedMod(string Guid, IRawProfileDataMod? ProfileData, IRawGlobalDataMod? GlobalData, IRawSaveDataMod? SaveData, IRawOnceSaveDataMod? 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;
			IRawProfileDataMod rawProfileDataMod = plugin as IRawProfileDataMod;
			IRawGlobalDataMod rawGlobalDataMod = plugin as IRawGlobalDataMod;
			IRawSaveDataMod rawSaveDataMod = plugin as IRawSaveDataMod;
			IRawOnceSaveDataMod rawOnceSaveDataMod = plugin as IRawOnceSaveDataMod;
			IRequiredMod requiredMod = plugin as IRequiredMod;
			if (rawProfileDataMod == null && rawGlobalDataMod == null && rawSaveDataMod == null && rawOnceSaveDataMod == null && requiredMod == null)
			{
				return false;
			}
			instance = new ManagedMod(gUID, rawProfileDataMod, rawGlobalDataMod, rawSaveDataMod, rawOnceSaveDataMod, requiredMod);
			DataManagerPlugin.InstanceLogger.LogInfo((object)(gUID + " uses data manager"));
			return true;
		}

		internal void LoadProfileData()
		{
			if (ProfileData != null)
			{
				LoadStreamData(ProfileDataPath, ProfileData.ReadProfileData);
			}
		}

		internal void SaveProfileData()
		{
			if (ProfileData != null && ProfileData.HasProfileData)
			{
				SaveStreamData(ProfileDataPath, ProfileData.WriteProfileData);
			}
		}

		internal void LoadGlobalData()
		{
			if (GlobalData != null)
			{
				LoadStreamData(GlobalDataPath, GlobalData.ReadGlobalData);
			}
		}

		internal void SaveGlobalData()
		{
			if (GlobalData != null && GlobalData.HasGlobalData)
			{
				SaveStreamData(GlobalDataPath, GlobalData.WriteGlobalData);
			}
		}

		internal void LoadSaveData(int saveSlot)
		{
			if (SaveData != null)
			{
				LoadStreamData(SaveDataPath(saveSlot), SaveData.ReadSaveData);
			}
		}

		internal void SaveSaveData(int saveSlot)
		{
			if (SaveData != null && SaveData.HasSaveData)
			{
				SaveStreamData(SaveDataPath(saveSlot), SaveData.WriteSaveData);
			}
		}

		internal void LoadOnceSaveData(int saveSlot)
		{
			if (OnceSaveData != null)
			{
				LoadStreamData(OnceSaveDataPath(saveSlot), OnceSaveData.ReadOnceSaveData);
			}
		}

		internal void SaveOnceSaveData(int saveSlot)
		{
			if (OnceSaveData != null && OnceSaveData.HasOnceSaveData)
			{
				SaveStreamData(OnceSaveDataPath(saveSlot), OnceSaveData.WriteOnceSaveData);
			}
		}

		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 LoadStreamData(string path, Action<Stream?> reader)
		{
			try
			{
				using FileStream obj = File.OpenRead(path);
				reader(obj);
			}
			catch (Exception ex) when (((ex is FileNotFoundException || ex is DirectoryNotFoundException) ? 1 : 0) != 0)
			{
				reader(null);
			}
			catch (Exception arg)
			{
				reader(null);
				DataManagerPlugin.InstanceLogger.LogError((object)$"Error loading data for mod {Guid}: {arg}");
			}
		}

		private void SaveStreamData(string path, Action<Stream> writer)
		{
			try
			{
				using FileStream obj = File.Create(path);
				writer(obj);
			}
			catch (Exception arg)
			{
				DataManagerPlugin.InstanceLogger.LogError((object)$"Error saving data 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 T? Deserialize<T>(StreamReader s)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			JsonTextReader val = new JsonTextReader((TextReader)s);
			try
			{
				return JsonSerializer.CreateDefault(_settings).Deserialize<T>((JsonReader)(object)val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		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(StreamWriter s, object value)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			JsonTextWriter val = new JsonTextWriter((TextWriter)s);
			try
			{
				JsonSerializer.CreateDefault(_settings).Serialize((JsonWriter)(object)val, value);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		internal static void Serialize(string path, object value)
		{
			using StreamWriter s = File.CreateText(path);
			Serialize(s, value);
		}
	}
}
namespace Silksong.DataManager.Data
{
	internal class DMOnceSaveData
	{
		public List<string> RequiredModGuids = new List<string>();
	}
}