Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MoreSaves v0.2.3
MoreSaves.dll
Decompiled 8 months agousing System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GlobalEnums; using HarmonyLib; using InControl; using Microsoft.CodeAnalysis; using TeamCherry.Localization; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; 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("MoreSaves")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.2.3.0")] [assembly: AssemblyInformationalVersion("0.2.3+acb51c1f725b511a54ae1b7bd03e772756728728")] [assembly: AssemblyProduct("MoreSaves")] [assembly: AssemblyTitle("MoreSaves")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Clazex/Silksong.MoreSaves")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.3.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 MoreSaves { internal static class ConfigEntries { internal static class Pagination { internal static ConfigField<int> MaxPages { get; } = new ConfigField<int>(25, "Max number of pages", (AcceptableValueBase?)(object)new AcceptableValueRange<int>(1, 50)); } internal static class KeyboardBindings { internal static ConfigKeyField PreviousPage { get; } = new ConfigKeyField((Key)0, "Previous page binding, uses the Inventory Pane Left binding (\"[\") when set to \"None\""); internal static ConfigKeyField NextPage { get; } = new ConfigKeyField((Key)0, "Next page binding, uses the Inventory Pane Right binding (\"]\") when set to \"None\""); } internal static class ControllerBindings { internal static ConfigField<InputControlType> PreviousPage { get; } = new ConfigField<InputControlType>((InputControlType)0, "Previous page binding, uses the Inventory Pane Left binding (\"LB\"/\"LT\") when set to \"None\""); internal static ConfigField<InputControlType> NextPage { get; } = new ConfigField<InputControlType>((InputControlType)0, "Next page binding, uses the Inventory Pane Right binding (\"RB\"/\"RT\") when set to \"None\""); } internal static class Experimental { internal static ConfigField<bool> SaveClipboard { get; } = new ConfigField<bool>(defaultValue: false, "Add a button for copying saves"); } internal class ConfigField<T> { private ConfigEntry<T>? entry; internal T DefaultValue { get; private init; } internal string Description { get; private init; } internal AcceptableValueBase? AcceptableValues { get; private init; } internal ConfigEntry<T> Entry { get { return entry ?? throw new InvalidOperationException("Not bound to entry"); } private set { entry = value; } } internal T Value => Entry.Value; public ConfigField(T defaultValue, string description, AcceptableValueBase? acceptableValues = null) { DefaultValue = defaultValue; Description = description; AcceptableValues = acceptableValues; base..ctor(); } internal void ResetToDefault() { Entry.Value = DefaultValue; } internal void Bind(ConfigFile config, string section, string key) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown if (entry != null) { throw new InvalidOperationException("Already bound to entry"); } Entry = config.Bind<T>(section, key, DefaultValue, new ConfigDescription(Description, AcceptableValues, Array.Empty<object>())); } } internal sealed class ConfigKeyField : ConfigField<Key> { private sealed class AcceptableKeyCodes : AcceptableValueBase { public AcceptableKeyCodes() : base(typeof(Key)) { } public override bool IsValid(object value) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (value is Key item) { return validKeyCodes.Contains(item); } return false; } public override object Clamp(object value) { if (!((AcceptableValueBase)this).IsValid(value)) { return (object)(Key)0; } return value; } public override string ToDescriptionString() { return "# Acceptable keys: " + string.Join(", ", validKeyCodes); } } private static readonly Dictionary<Key, Key> mappings; private static readonly HashSet<Key> validKeyCodes; internal Key Key => mappings[base.Value]; public ConfigKeyField(Key defaultValue, string description) : base(defaultValue, description, (AcceptableValueBase?)(object)new AcceptableKeyCodes()) { }//IL_0001: Unknown result type (might be due to invalid IL or missing references) static ConfigKeyField() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) mappings = new Dictionary<Key, Key>(); KeyMapping[] keyMappings = UnityKeyboardProvider.KeyMappings; foreach (KeyMapping val in keyMappings) { mappings[val.target0] = val.source; mappings[val.target1] = val.source; } mappings[(Key)0] = (Key)0; HashSet<Key> hashSet = new HashSet<Key>(); foreach (Key key in mappings.Keys) { hashSet.Add(key); } validKeyCodes = hashSet; } } internal static void Bind(ConfigFile config) { config.Bind(Pagination.MaxPages, "Pagination.MaxPages"); config.Bind(KeyboardBindings.PreviousPage, "KeyboardBindings.PreviousPage"); config.Bind(KeyboardBindings.NextPage, "KeyboardBindings.NextPage"); config.Bind(ControllerBindings.PreviousPage, "ControllerBindings.PreviousPage"); config.Bind(ControllerBindings.NextPage, "ControllerBindings.NextPage"); config.Bind(Experimental.SaveClipboard, "Experimental.SaveClipboard"); } private static void Bind<T>(this ConfigFile config, ConfigField<T> field, [CallerArgumentExpression("field")] string name = "") { string[] array = name.Split('.', StringSplitOptions.RemoveEmptyEntries); if (array != null && array.Length == 2) { string text = array[0]; if (text != null) { string text2 = array[1]; if (text2 != null) { field.Bind(config, text, text2); return; } } } throw new InvalidOperationException("Unexpected field name: " + name); } } [RequireComponent(typeof(MenuButton))] internal sealed class CopySaveController : MonoBehaviour { [CompilerGenerated] private static CopySaveController <Instance>k__BackingField; private GameObject textChild; private Text text; private FixVerticalAlign textAligner; internal static CopySaveController Instance { get { if (!((Object)(object)<Instance>k__BackingField != (Object)null)) { throw new InvalidOperationException("instance not present"); } return <Instance>k__BackingField; } private set { <Instance>k__BackingField = value; } } internal static void Setup(UIManager ui) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)ui.saveProfileControls).gameObject; GameObject gameObject2 = ((Component)gameObject.transform.Find("BackButton")).gameObject; MenuButton component = gameObject2.GetComponent<MenuButton>(); GameObject obj = Object.Instantiate<GameObject>(gameObject2, gameObject.transform); ((Object)obj).name = "CopySaveButton"; obj.transform.Translate(0f, -1.25f, 0f); Object.DestroyImmediate((Object)(object)obj.GetComponent<EventTrigger>()); obj.AddComponent<CopySaveController>(); SaveClipboard.CancelCopy(); MenuButton component2 = obj.GetComponent<MenuButton>(); component2.buttonType = (MenuButtonType)1; Navigation navigation = ((Selectable)component).navigation; ((Navigation)(ref navigation)).selectOnDown = (Selectable)(object)component2; ((Selectable)component).navigation = navigation; navigation = ((Selectable)component2).navigation; ((Navigation)(ref navigation)).selectOnUp = (Selectable)(object)component; ((Selectable)component2).navigation = navigation; } internal static void OnStateChanged(SaveClipboard.ClipboardState state) { SetSaveButtonsDeselect(state == SaveClipboard.ClipboardState.Idle); Instance.RefreshText(); } private static void SetSaveButtonsDeselect(bool doDeselect) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) MenuButtonType type = (MenuButtonType)((!doDeselect) ? 1 : 0); CoreLoop.InvokeNext((Action)delegate { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) SaveSlotButton[] buttons = SavePageState.buttons; for (int i = 0; i < buttons.Length; i++) { ((MenuButton)buttons[i]).buttonType = type; } }); } private static string GetText() { return SaveClipboard.State switch { SaveClipboard.ClipboardState.Idle => Lang.Get("CopyIdle"), SaveClipboard.ClipboardState.CopySelect => Lang.Get("CopySelect"), SaveClipboard.ClipboardState.PasteSelect => string.Format(Lang.Get("CopySelected"), SaveClipboard.SaveName), _ => throw new InvalidOperationException(), }; } private void Awake() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Instance = this; MenuButton component = ((Component)this).GetComponent<MenuButton>(); ((MenuSelectable)component).cancelAction = (CancelAction)1; UnityEvent val = new UnityEvent(); val.AddListener(new UnityAction(SaveClipboard.StartCopy)); component.OnSubmitPressed = val; textChild = ((Component)((Component)this).transform.Find("Menu Button Text")).gameObject; text = textChild.GetComponent<Text>(); textAligner = textChild.GetComponent<FixVerticalAlign>(); Object.DestroyImmediate((Object)(object)textChild.GetComponent<AutoLocalizeTextUI>()); GameManager.instance.RefreshLanguageText += RefreshText; RefreshText(); } private void OnDestroy() { GameManager.instance.RefreshLanguageText -= RefreshText; } private void RefreshText() { text.text = GetText(); textAligner.AlignText(); } } internal static class Lang { internal static string Get(string key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if ((int)Language.CurrentLanguage() == 199) { return key switch { "CopyIdle" => "复制存档", "CopySelect" => "选择要复制的存档", "SaveIndex" => "#{0}", "SaveIndexWithName" => "#{0}({1})", "CopySelected" => "已复制存档 {0}", _ => key, }; } return key switch { "CopyIdle" => "Copy Save", "CopySelect" => "Select Save to Copy", "SaveIndex" => "#{0}", "SaveIndexWithName" => "#{0} ({1})", "CopySelected" => "Copied Save {0}", _ => key, }; } } [BepInPlugin("dev.clazex.moresaves", "MoreSaves", "0.2.3")] public sealed class MoreSavesPlugin : BaseUnityPlugin { public const string Id = "dev.clazex.moresaves"; public static MoreSavesPlugin Instance { get; private set; } = null; internal static ManualLogSource Logger { get; private set; } = null; private static Harmony Harmony { get; } = new Harmony("dev.clazex.moresaves"); public static string Name => "MoreSaves"; public static string Version => "0.2.3"; internal static event Action<ConfigEntryBase?>? ConfigChanged; private static void InvokeConfigChanged(ConfigEntryBase? entry) { if (entry != null) { Logger.LogDebug((object)("Config changed: " + entry.Definition.Section + "." + entry.Definition.Key)); } else { Logger.LogDebug((object)"Config changed"); } MoreSavesPlugin.ConfigChanged?.Invoke(entry); } private void Awake() { Instance = this; Logger = ((BaseUnityPlugin)this).Logger; ConfigEntries.Bind(((BaseUnityPlugin)this).Config); ((BaseUnityPlugin)this).Config.ConfigReloaded += delegate { InvokeConfigChanged(null); }; ((BaseUnityPlugin)this).Config.SettingChanged += delegate(object _, SettingChangedEventArgs args) { InvokeConfigChanged(args.ChangedSetting); }; Harmony.PatchAll(typeof(Patches)); Logger.LogInfo((object)("Plugin " + Name + " (dev.clazex.moresaves) v" + Version + " has loaded!")); } private void OnDestroy() { Logger.LogWarning((object)"Unload called in release build"); Harmony.UnpatchSelf(); Logger.LogInfo((object)("Plugin " + Name + " has unloaded!")); } } internal sealed class NavigationActionSet : PlayerActionSet { private readonly PlayerAction keyboardPrev; private readonly PlayerAction keyboardNext; private readonly PlayerAction controllerPrev; private readonly PlayerAction controllerNext; internal static NavigationActionSet Instance { get; private set; } internal bool PrevIsPressed { get { if (!((OneAxisInputControl)keyboardPrev).IsPressed) { return ((OneAxisInputControl)controllerPrev).IsPressed; } return true; } } internal bool PrevWasPressed { get { if (!((OneAxisInputControl)keyboardPrev).WasPressed) { return ((OneAxisInputControl)controllerPrev).WasPressed; } return true; } } internal bool PrevWasRepeated { get { if (!((OneAxisInputControl)keyboardPrev).WasRepeated) { return ((OneAxisInputControl)controllerPrev).WasRepeated; } return true; } } internal bool NextIsPressed { get { if (!((OneAxisInputControl)keyboardNext).IsPressed) { return ((OneAxisInputControl)controllerNext).IsPressed; } return true; } } internal bool NextWasPressed { get { if (!((OneAxisInputControl)keyboardNext).WasPressed) { return ((OneAxisInputControl)controllerNext).WasPressed; } return true; } } internal bool NextWasRepeated { get { if (!((OneAxisInputControl)keyboardNext).WasRepeated) { return ((OneAxisInputControl)controllerNext).WasRepeated; } return true; } } internal static void Reload() { Instance = new NavigationActionSet(); } static NavigationActionSet() { Instance = new NavigationActionSet(); MoreSavesPlugin.ConfigChanged += delegate(ConfigEntryBase? entry) { bool flag = entry == null; if (!flag) { string section = entry.Definition.Section; bool flag2 = ((section == "KeyboardBindings" || section == "ControllerBindings") ? true : false); flag = flag2; } if (flag) { Reload(); } }; } private NavigationActionSet() { //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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected I4, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected I4, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) MoreSavesPlugin.Logger.LogDebug((object)"Creating navigation action set"); HeroActions inputActions = ManagerSingleton<InputHandler>.Instance.inputActions; Key key = ConfigEntries.KeyboardBindings.PreviousPage.Key; if ((int)key != 0) { keyboardPrev = new PlayerAction("Keyboard Prev Page", (PlayerActionSet)(object)this); keyboardPrev.AddDefaultBinding((Key[])(object)new Key[1] { (Key)(int)key }); } else { keyboardPrev = inputActions.PaneLeft; } Key key2 = ConfigEntries.KeyboardBindings.NextPage.Key; if ((int)key2 != 0) { keyboardNext = new PlayerAction("Keyboard Next Page", (PlayerActionSet)(object)this); keyboardNext.AddDefaultBinding((Key[])(object)new Key[1] { (Key)(int)key2 }); } else { keyboardNext = inputActions.PaneRight; } InputControlType value = ConfigEntries.ControllerBindings.PreviousPage.Value; if ((int)value != 0) { controllerPrev = new PlayerAction("Controller Prev Page", (PlayerActionSet)(object)this); controllerPrev.AddDefaultBinding(value); } else { controllerPrev = inputActions.PaneLeft; } InputControlType value2 = ConfigEntries.ControllerBindings.NextPage.Value; if ((int)value2 != 0) { controllerNext = new PlayerAction("Controller Next Page", (PlayerActionSet)(object)this); controllerNext.AddDefaultBinding(value2); } else { controllerNext = inputActions.PaneRight; } } } internal static class Patches { [CompilerGenerated] private sealed class <CancelCopyOnReturn>d__11 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator __result; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CancelCopyOnReturn>d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (__result.MoveNext()) { <>2__current = __result.Current; <>1__state = 1; return true; } SaveClipboard.CancelCopy(); 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(); } } [HarmonyPatch(typeof(UIManager), "Start")] [HarmonyWrapSafe] [HarmonyPrefix] private static void Setup(UIManager __instance) { SavePageState.buttons = (SaveSlotButton[])(object)new SaveSlotButton[4] { __instance.slotOne, __instance.slotTwo, __instance.slotThree, __instance.slotFour }; SavePageState.SetPageByLastIndex(); SaveSlotButton[] buttons = SavePageState.buttons; foreach (SaveSlotButton val in buttons) { Text component = ((Component)val.slotNumberText).GetComponent<Text>(); component.horizontalOverflow = (HorizontalWrapMode)1; component.alignment = (TextAnchor)6; ((Component)component).transform.Translate(0.34f, 0f, 0f); component.text = SavePageState.GenerateSlotNumberText(val); } if (ConfigEntries.Experimental.SaveClipboard.Value) { CopySaveController.Setup(__instance); } ((Component)__instance).gameObject.AddComponent<SavePageNavigator>(); MoreSavesPlugin.Logger.LogDebug((object)"Setup complete"); } [HarmonyPatch(typeof(UIManager), "UIGoToProfileMenu")] [HarmonyWrapSafe] [HarmonyPrefix] private static void UpdatePage() { SavePageState.SetPageByLastIndex(); } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyWrapSafe] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ModifyGoToProfileSequence(IEnumerable<CodeInstruction> insts) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown return new CodeMatcher(insts, (ILGenerator)null).MatchForward(true, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Stloc_2, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldloc_2, (object)null, (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Call, (object)(MethodInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/)), new CodeInstruction(OpCodes.Sub, (object)null) }) .MatchForward(true, (CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)(MethodInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/), (string)null), new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)null, (string)null) }) .SetOperandAndAdvance((object)0f) .InstructionEnumeration(); } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyWrapSafe] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HideButtonsAtOnce(IEnumerable<CodeInstruction> insts) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown return new CodeMatcher(insts, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)0.165f, (string)null) }).Repeat((Action<CodeMatcher>)delegate(CodeMatcher matcher) { matcher.SetOperandAndAdvance((object)0f); }, (Action<string>)null).InstructionEnumeration(); } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyWrapSafe] [HarmonyPostfix] private static void OffsetSlotIndex(ref int __result) { __result += SavePageState.CurrentIndexBase; } [HarmonyPatch(typeof(Platform), "IsSaveSlotIndexValid")] [HarmonyWrapSafe] [HarmonyPostfix] private static void MakeAllIndicesValid(int slotIndex, ref bool __result) { __result = slotIndex >= 0; } [HarmonyPatch(typeof(SaveSlotButton), "Awake")] [HarmonyPatch(typeof(SaveSlotButton), "Prepare")] [HarmonyWrapSafe] [HarmonyPrefix] private static void UpdateSlotNumberText(SaveSlotButton __instance) { ((Component)__instance.slotNumberText).GetComponent<Text>().text = SavePageState.GenerateSlotNumberText(__instance); } [HarmonyPatch(typeof(UIManager), "UIContinueGame", new Type[] { typeof(int), typeof(SaveGameData) })] [HarmonyWrapSafe] [HarmonyPrefix] private static bool SelectSaveNonempty(int slot, SaveGameData saveGameData) { return SaveClipboard.Select(slot, saveGameData, (AutoSaveName)0); } [HarmonyPatch(typeof(UIManager), "UIGoToPlayModeMenu")] [HarmonyPatch(typeof(UIManager), "StartNewGame")] [HarmonyWrapSafe] [HarmonyPrefix] private static bool SelectSaveEmpty(UIManager __instance) { return SaveClipboard.Select(__instance.gm.profileID, null, (AutoSaveName)0); } [HarmonyPatch(typeof(RestoreSaveButton), "SaveSelected")] [HarmonyWrapSafe] [HarmonyPrefix] private static bool SelectRestorePoint(RestoreSaveButton __instance, RestorePointData restorePointData) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) bool num = SaveClipboard.Select(__instance.saveSlotButton.SaveSlotIndex, restorePointData.saveGameData, restorePointData.autoSaveName); if (!num) { __instance.saveSlotButton.ShowRelevantModeForSaveFileState(); } return num; } [HarmonyPatch(typeof(ClearSaveButton), "OnSubmit")] [HarmonyWrapSafe] [HarmonyPrefix] private static void CancelCopyOnClear() { SaveClipboard.CancelCopy(); } [IteratorStateMachine(typeof(<CancelCopyOnReturn>d__11))] [HarmonyPatch(typeof(UIManager), "HideSaveProfileMenu")] [HarmonyWrapSafe] [HarmonyPostfix] private static IEnumerator CancelCopyOnReturn(IEnumerator __result) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CancelCopyOnReturn>d__11(0) { __result = __result }; } } internal static class SaveClipboard { internal enum ClipboardState { Idle, CopySelect, PasteSelect } [CompilerGenerated] private sealed class <>c__DisplayClass15_0 { public bool? result; internal void <PasteSaveCoro>b__0(bool success) { result = success; } internal bool <PasteSaveCoro>b__1() { return result.HasValue; } } [CompilerGenerated] private sealed class <PasteSaveCoro>d__15 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public int slot; private <>c__DisplayClass15_0 <>8__1; private GameManager <gm>5__2; private InputHandler <ih>5__3; private SaveSlotButton <button>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PasteSaveCoro>d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <gm>5__2 = null; <ih>5__3 = null; <button>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass15_0(); <gm>5__2 = GameManager.instance; <ih>5__3 = ManagerSingleton<InputHandler>.Instance; <ih>5__3.StopUIInput(); <>8__1.result = null; Platform.Current.WriteSaveSlot(slot, <gm>5__2.GetBytesForSaveData(data), (Action<bool>)delegate(bool success) { <>8__1.result = success; }); <>2__current = (object)new WaitUntil((Func<bool>)(() => <>8__1.result.HasValue)); <>1__state = 1; return true; case 1: <>1__state = -1; <button>5__4 = SavePageState.GetButtonForSlot(slot); <button>5__4.ResetButton(<gm>5__2, false, true); <>2__current = SavePageState.loadSaveWait; <>1__state = 2; return true; case 2: <>1__state = -1; <button>5__4.Prepare(<gm>5__2, false, true, false); if (<>8__1.result.Value) { State = ClipboardState.Idle; MoreSavesPlugin.Logger.LogDebug((object)$"Pasted save into {slot}"); } else { MoreSavesPlugin.Logger.LogError((object)$"Failed to paste save into {slot}"); } <ih>5__3.StartUIInput(); 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(); } } [CompilerGenerated] private static ClipboardState <State>k__BackingField; private static int saveIndex; private static AutoSaveName name; private static SaveGameData? data; internal static ClipboardState State { [CompilerGenerated] get { return <State>k__BackingField; } private set { <State>k__BackingField = value; CopySaveController.OnStateChanged(value); } } internal static string SaveName { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if ((int)name != 0) { return string.Format(Lang.Get("SaveIndexWithName"), saveIndex, GameManager.GetFormattedAutoSaveNameString(name)); } return string.Format(Lang.Get("SaveIndex"), saveIndex); } } internal static void StartCopy() { if (State == ClipboardState.Idle) { State = ClipboardState.CopySelect; MoreSavesPlugin.Logger.LogDebug((object)"Copy started"); } else { CancelCopy(); } } internal static void CancelCopy() { if (State == ClipboardState.Idle) { MoreSavesPlugin.Logger.LogDebug((object)"Not copying, remain idle"); return; } saveIndex = 0; data = null; State = ClipboardState.Idle; MoreSavesPlugin.Logger.LogDebug((object)"Copy cancelled"); } internal static bool Select(int slot, SaveGameData? saveData, AutoSaveName autoSaveName = 0) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (State == ClipboardState.Idle) { return true; } if (saveData == null) { if (State == ClipboardState.PasteSelect) { PasteSave(slot); } else { CancelCopy(); } } else if (State == ClipboardState.CopySelect) { CopySave(slot, saveData, autoSaveName); } else { CancelCopy(); } return false; } private static void CopySave(int slot, SaveGameData saveGameData, AutoSaveName autoSaveName) { //IL_0032: 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) if (State != ClipboardState.CopySelect) { MoreSavesPlugin.Logger.LogError((object)$"State {State} is invalid to copy save"); CancelCopy(); return; } saveIndex = slot; name = autoSaveName; data = saveGameData; State = ClipboardState.PasteSelect; MoreSavesPlugin.Logger.LogDebug((object)("Copied save " + SaveName)); } private static void PasteSave(int slot) { MoreSavesPlugin.Logger.LogDebug((object)"Start pasting"); ((MonoBehaviour)CopySaveController.Instance).StartCoroutine(PasteSaveCoro(slot)); } [IteratorStateMachine(typeof(<PasteSaveCoro>d__15))] private static IEnumerator PasteSaveCoro(int slot) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PasteSaveCoro>d__15(0) { slot = slot }; } } [RequireComponent(typeof(UIManager))] internal sealed class SavePageNavigator : MonoBehaviour { private const int BULK_NAVIGATE_STRIDE = 5; private const float BULK_NAVIGATE_COOLDOWN = 0.5f; private UIManager ui; private InputHandler ih; private float bulkNavCooldown; private static NavigationActionSet Actions => NavigationActionSet.Instance; private void Awake() { ui = ((Component)this).GetComponent<UIManager>(); ih = ui.ih; NavigationActionSet.Reload(); MoreSavesPlugin.Logger.LogDebug((object)"Navigator awake"); } private void Update() { if (bulkNavCooldown > 0f) { bulkNavCooldown -= Time.unscaledDeltaTime; } if (ih.acceptingInput && Object.op_Implicit((Object)(object)ui.saveProfileControls) && ui.saveProfileControls.interactable && (Actions.PrevIsPressed || Actions.NextIsPressed) && (!Actions.PrevIsPressed || !Actions.NextIsPressed)) { if (Actions.PrevWasPressed || Actions.NextWasPressed) { MoreSavesPlugin.Logger.LogDebug((object)"Attempt navigating"); AttemptNavigate(Actions.NextWasPressed); } else if ((Actions.PrevWasRepeated || Actions.NextWasRepeated) && !(bulkNavCooldown > 0f)) { bulkNavCooldown = 0.5f; MoreSavesPlugin.Logger.LogDebug((object)"Attempt bulk navigating"); AttemptNavigate(Actions.NextWasRepeated, 5); } } } private static void AttemptNavigate(bool forward, int stride = 1) { int num = Math.Clamp(SavePageState.CurrentPage + (forward ? 1 : (-1)) * stride, 0, ConfigEntries.Pagination.MaxPages.Value - 1); if (num == SavePageState.CurrentPage) { MoreSavesPlugin.Logger.LogDebug((object)"Page unchanged"); } else { SavePageState.StartNavigation(num); } } } internal static class SavePageState { [CompilerGenerated] private sealed class <NavigationCoro>d__21 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private GameManager <gm>5__2; private UIManager <ui>5__3; private int <highlight>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <NavigationCoro>d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <gm>5__2 = null; <ui>5__3 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; <gm>5__2 = GameManager.instance; <ui>5__3 = UIManager.instance; <highlight>5__4 = GetLastSlotIndex(); SaveSlotButton[] buttons = SavePageState.buttons; for (int i = 0; i < buttons.Length; i++) { buttons[i].ResetButton(<gm>5__2, false, true); } <>2__current = loadSaveWait; <>1__state = 1; return true; } case 1: { <>1__state = -1; SaveSlotButton[] buttons = SavePageState.buttons; foreach (SaveSlotButton val in buttons) { val.Prepare(<gm>5__2, false, true, false); if (val.SaveSlotIndex == <highlight>5__4) { <ui>5__3.saveSlots.itemToHighlight = (Selectable)(object)val; <ui>5__3.saveSlots.HighlightDefault(false); } } LastPage = CurrentPage; MoreSavesPlugin.Logger.LogDebug((object)"Navigating finished"); ManagerSingleton<InputHandler>.Instance.StartUIInput(); 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(); } } internal const int SLOTS_PER_PAGE = 4; internal static readonly WaitForSecondsRealtime loadSaveWait = new WaitForSecondsRealtime(0.2f); internal static SaveSlotButton[] buttons = Array.Empty<SaveSlotButton>(); internal static int CurrentPage { get; private set; } = 0; private static int LastPage { get; set; } = 0; internal static int CurrentIndexBase => CurrentPage * 4; private static bool IsChangingPage => CurrentPage != LastPage; private static int GetLastSlotIndex() { return Platform.Current.LocalSharedData.GetInt("lastProfileIndex", 0); } private static int GetPageForSlot(int slot) { return Mathf.FloorToInt(((float)slot - 1f) / 4f); } internal static SaveSlotButton GetButtonForSlot(int slot) { return buttons[(slot - 1) % 4]; } internal static string GenerateSlotNumberText(SaveSlotButton button) { return $"{button.SaveSlotIndex}."; } internal static void SetPageByLastIndex() { LastPage = (CurrentPage = GetPageForSlot(GetLastSlotIndex())); } internal static void StartNavigation(int targetPage) { if (targetPage < 0 || targetPage >= ConfigEntries.Pagination.MaxPages.Value) { throw new ArgumentOutOfRangeException("targetPage"); } if (IsChangingPage) { throw new InvalidOperationException("Page is already changing"); } ManagerSingleton<InputHandler>.Instance.StopUIInput(); CurrentPage = targetPage; MoreSavesPlugin.Logger.LogDebug((object)$"Start navigating to page {targetPage}"); ((MonoBehaviour)UIManager.instance).StartCoroutine(NavigationCoro()); } [IteratorStateMachine(typeof(<NavigationCoro>d__21))] private static IEnumerator NavigationCoro() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <NavigationCoro>d__21(0); } } } internal class MoreSaves_ProcessedByFody { internal const string FodyVersion = "6.9.3.0"; internal const string InfoOf = "2.2.0.0"; }