diff --git a/build/common.props b/build/common.props index 126fa0b0..d9029485 100644 --- a/build/common.props +++ b/build/common.props @@ -4,7 +4,7 @@ 1.0.0 v$(GameVersion) - 5.10.1 + 5.10.2 2.2.2 2.8.15 2.8.1 diff --git a/changelog.txt b/changelog.txt index e731df86..0c6fab15 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,8 @@ --------------------------------------------------------------------------------------------------- +Version: 5.10.2 +Game Versions: v1.0.0,v1.0.1,v1.0.2,v1.0.3,v1.1.0,v1.1.1,v1.1.2,v1.1.3,v1.1.4,v1.1.5,v1.1.6,v1.2.x +* Added the ability to set group order of empty groups +--------------------------------------------------------------------------------------------------- Version: 5.10.1 Game Versions: v1.0.0,v1.0.1,v1.0.2,v1.0.3,v1.1.0,v1.1.1,v1.1.2,v1.1.3,v1.1.4,v1.1.5,v1.1.6,v1.2.x * Reverted Settings instance cache and cache invalidation diff --git a/docs/articles/MCMv5/mcmv5-attributes.md b/docs/articles/MCMv5/mcmv5-attributes.md index 223a2185..45617b24 100644 --- a/docs/articles/MCMv5/mcmv5-attributes.md +++ b/docs/articles/MCMv5/mcmv5-attributes.md @@ -117,6 +117,12 @@ You can order properties via the [``Order``](xref:MCM.Abstractions.Attributes.Ba [SettingPropertyText("Setting Name", Order = 6)] public string SettingVariableName { get; set; } = "The textbox data is here"; ``` +If your group is empty (there are no properties that could indicate the group's order), you can use xref:MCM.Abstractions.Attributes.SettingPropertyGroupAttribute to order the group +```csharp +[SettingPropertyGroupMetadata] +[SettingPropertyGroup("EmptyGroup", GroupOrder = 3)] +public object EmptyGroupMetadata { get; set; } = new(); +``` #### Require Restart You can the game to restart when the property changes via the [``RequireRestart``](xref:MCM.Abstractions.Attributes.BaseSettingPropertyAttribute#collapsible-MCM_Abstractions_Attributes_BaseSettingPropertyAttribute_RequireRestart) attribute property diff --git a/src/MCM.Abstractions/Base/Global/BaseFluentGlobalSettingsWrapper.cs b/src/MCM.Abstractions/Base/Global/BaseFluentGlobalSettingsWrapper.cs deleted file mode 100644 index 9727a946..00000000 --- a/src/MCM.Abstractions/Base/Global/BaseFluentGlobalSettingsWrapper.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MCM.Abstractions.FluentBuilder; -using MCM.Common; - -using System; -using System.Collections.Generic; -using System.ComponentModel; - -namespace MCM.Abstractions.Base.Global -{ - [Obsolete("Will be removed from future API", true)] -#if !BANNERLORDMCM_INCLUDE_IN_CODE_COVERAGE - [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage, global::System.Diagnostics.DebuggerNonUserCode] -#endif -#if !BANNERLORDMCM_PUBLIC - internal -#else - public -# endif - abstract class BaseFluentGlobalSettingsWrapper : FluentGlobalSettings, IWrapper - { - /// - public object Object { get; protected set; } - - protected BaseFluentGlobalSettingsWrapper(object @object, string id, string displayName, string folderName, string subFolder, string format, int uiVersion, char subGroupDelimiter, PropertyChangedEventHandler? onPropertyChanged, IEnumerable settingPropertyGroups, IEnumerable presets) - : base(id, displayName, folderName, subFolder, format, uiVersion, subGroupDelimiter, onPropertyChanged, settingPropertyGroups, presets) - { - Object = @object; - } - } -} \ No newline at end of file diff --git a/src/MCM.Abstractions/Base/Global/BaseGlobalSettingsWrapper.cs b/src/MCM.Abstractions/Base/Global/BaseGlobalSettingsWrapper.cs deleted file mode 100644 index 5ed13d37..00000000 --- a/src/MCM.Abstractions/Base/Global/BaseGlobalSettingsWrapper.cs +++ /dev/null @@ -1,26 +0,0 @@ -using MCM.Common; - -using System; - -namespace MCM.Abstractions.Base.Global -{ - [Obsolete("Will be removed from future API", true)] -#if !BANNERLORDMCM_INCLUDE_IN_CODE_COVERAGE - [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage, global::System.Diagnostics.DebuggerNonUserCode] -#endif -#if !BANNERLORDMCM_PUBLIC - internal -#else - public -# endif - abstract class BaseGlobalSettingsWrapper : GlobalSettings, IWrapper - { - /// - public object Object { get; protected set; } - - protected BaseGlobalSettingsWrapper(object @object) - { - Object = @object; - } - } -} \ No newline at end of file diff --git a/src/MCM.Abstractions/Base/Global/FluentGlobalSettings.cs b/src/MCM.Abstractions/Base/Global/FluentGlobalSettings.cs index d2e9fef2..51bdc550 100644 --- a/src/MCM.Abstractions/Base/Global/FluentGlobalSettings.cs +++ b/src/MCM.Abstractions/Base/Global/FluentGlobalSettings.cs @@ -59,7 +59,7 @@ public FluentGlobalSettings(string id, string displayName, string folderName, st public void Register() { - var containers = GenericServiceProvider.GetService>() ?? Enumerable.Empty(); + var containers = GenericServiceProvider.GetService>() ?? []; foreach (var container in containers) { container?.Register(this); @@ -67,7 +67,7 @@ public void Register() } public void Unregister() { - var containers = GenericServiceProvider.GetService>() ?? Enumerable.Empty(); + var containers = GenericServiceProvider.GetService>() ?? []; foreach (var container in containers) { container?.Unregister(this); diff --git a/src/MCM.Abstractions/Base/PerCampaign/BasePerCampaignSettingsWrapper.cs b/src/MCM.Abstractions/Base/PerCampaign/BasePerCampaignSettingsWrapper.cs deleted file mode 100644 index bfbd00e2..00000000 --- a/src/MCM.Abstractions/Base/PerCampaign/BasePerCampaignSettingsWrapper.cs +++ /dev/null @@ -1,78 +0,0 @@ -using HarmonyLib.BUTR.Extensions; - -using MCM.Common; - -using System; -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace MCM.Abstractions.Base.PerCampaign -{ - [Obsolete("Will be removed from future API", true)] -#if !BANNERLORDMCM_INCLUDE_IN_CODE_COVERAGE - [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage, global::System.Diagnostics.DebuggerNonUserCode] -#endif -#if !BANNERLORDMCM_PUBLIC - internal -#else - public -# endif - abstract class BasePerCampaignSettingsWrapper : PerCampaignSettings, IWrapper - { - private delegate string GetIdDelegate(); - private delegate string GetFolderNameDelegate(); - private delegate string GetDisplayNameDelegate(); - private delegate int GetUIVersionDelegate(); - private delegate string GetSubFolderDelegate(); - private delegate char GetSubGroupDelimiterDelegate(); - private delegate void OnPropertyChangedDelegate(string? propertyName); - - private readonly GetIdDelegate? _getIdDelegate; - private readonly GetFolderNameDelegate? _getFolderNameDelegate; - private readonly GetDisplayNameDelegate? _getDisplayNameDelegate; - private readonly GetUIVersionDelegate? _getUIVersionDelegate; - private readonly GetSubFolderDelegate? _getSubFolderDelegate; - private readonly GetSubGroupDelimiterDelegate? _getSubGroupDelimiterDelegate; - private readonly OnPropertyChangedDelegate? _methodOnPropertyChangedDelegate; - - /// - public object Object { get; protected set; } - - /// - public override string Id => _getIdDelegate?.Invoke() ?? "ERROR"; - /// - public override string FolderName => _getFolderNameDelegate?.Invoke() ?? string.Empty; - /// - public override string DisplayName => _getDisplayNameDelegate?.Invoke() ?? "ERROR"; - /// - public override int UIVersion => _getUIVersionDelegate?.Invoke() ?? 1; - /// - public override string SubFolder => _getSubFolderDelegate?.Invoke() ?? string.Empty; - /// - public override char SubGroupDelimiter => _getSubGroupDelimiterDelegate?.Invoke() ?? '/'; - /// - public override event PropertyChangedEventHandler? PropertyChanged - { - add { if (Object is INotifyPropertyChanged notifyPropertyChanged) notifyPropertyChanged.PropertyChanged += value; } - remove { if (Object is INotifyPropertyChanged notifyPropertyChanged) notifyPropertyChanged.PropertyChanged -= value; } - } - - protected BasePerCampaignSettingsWrapper(object @object) - { - Object = @object; - var type = @object.GetType(); - - _getIdDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(Id)); - _getFolderNameDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(FolderName)); - _getDisplayNameDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(DisplayName)); - _getUIVersionDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(UIVersion)); - _getSubFolderDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(SubFolder)); - _getSubGroupDelimiterDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(SubGroupDelimiter)); - _methodOnPropertyChangedDelegate = AccessTools2.GetDelegate(@object, type, nameof(OnPropertyChanged)); - } - - /// - public override void OnPropertyChanged([CallerMemberName] string? propertyName = null) => - _methodOnPropertyChangedDelegate?.Invoke(propertyName); - } -} \ No newline at end of file diff --git a/src/MCM.Abstractions/Base/PerCampaign/FluentPerCampaignSettings.cs b/src/MCM.Abstractions/Base/PerCampaign/FluentPerCampaignSettings.cs index fd6f1b2f..162243a2 100644 --- a/src/MCM.Abstractions/Base/PerCampaign/FluentPerCampaignSettings.cs +++ b/src/MCM.Abstractions/Base/PerCampaign/FluentPerCampaignSettings.cs @@ -56,7 +56,7 @@ public FluentPerCampaignSettings(string id, string displayName, string folderNam public void Register() { // TODO: check - var containers = GenericServiceProvider.GetService>() ?? Enumerable.Empty(); + var containers = GenericServiceProvider.GetService>() ?? []; foreach (var container in containers) { container?.Register(this); @@ -65,7 +65,7 @@ public void Register() public void Unregister() { // TODO: check - var containers = GenericServiceProvider.GetService>() ?? Enumerable.Empty(); + var containers = GenericServiceProvider.GetService>() ?? []; foreach (var container in containers) { container?.Unregister(this); diff --git a/src/MCM.Abstractions/Base/PerCampaign/PerCampaignSettings.cs b/src/MCM.Abstractions/Base/PerCampaign/PerCampaignSettings.cs index 9fd92a84..5e558800 100644 --- a/src/MCM.Abstractions/Base/PerCampaign/PerCampaignSettings.cs +++ b/src/MCM.Abstractions/Base/PerCampaign/PerCampaignSettings.cs @@ -25,7 +25,7 @@ public static T? Instance return BaseSettingsProvider.Instance?.GetSettings(Cache[typeof(T)]) as T; } } - + /* /// /// A modder flriendly way to get settings from any place diff --git a/src/MCM.Abstractions/Base/PerSave/BasePerSaveSettingsWrapper.cs b/src/MCM.Abstractions/Base/PerSave/BasePerSaveSettingsWrapper.cs deleted file mode 100644 index a4b5962d..00000000 --- a/src/MCM.Abstractions/Base/PerSave/BasePerSaveSettingsWrapper.cs +++ /dev/null @@ -1,78 +0,0 @@ -using HarmonyLib.BUTR.Extensions; - -using MCM.Common; - -using System; -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace MCM.Abstractions.Base.PerSave -{ - [Obsolete("Will be removed from future API", true)] -#if !BANNERLORDMCM_INCLUDE_IN_CODE_COVERAGE - [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage, global::System.Diagnostics.DebuggerNonUserCode] -#endif -#if !BANNERLORDMCM_PUBLIC - internal -#else - public -# endif - abstract class BasePerSaveSettingsWrapper : PerSaveSettings, IWrapper - { - private delegate string GetIdDelegate(); - private delegate string GetFolderNameDelegate(); - private delegate string GetDisplayNameDelegate(); - private delegate int GetUIVersionDelegate(); - private delegate string GetSubFolderDelegate(); - private delegate char GetSubGroupDelimiterDelegate(); - private delegate void OnPropertyChangedDelegate(string? propertyName); - - private readonly GetIdDelegate? _getIdDelegate; - private readonly GetFolderNameDelegate? _getFolderNameDelegate; - private readonly GetDisplayNameDelegate? _getDisplayNameDelegate; - private readonly GetUIVersionDelegate? _getUIVersionDelegate; - private readonly GetSubFolderDelegate? _getSubFolderDelegate; - private readonly GetSubGroupDelimiterDelegate? _getSubGroupDelimiterDelegate; - private readonly OnPropertyChangedDelegate? _methodOnPropertyChangedDelegate; - - /// - public object Object { get; protected set; } - - /// - public override string Id => _getIdDelegate?.Invoke() ?? "ERROR"; - /// - public override string FolderName => _getFolderNameDelegate?.Invoke() ?? string.Empty; - /// - public override string DisplayName => _getDisplayNameDelegate?.Invoke() ?? "ERROR"; - /// - public override int UIVersion => _getUIVersionDelegate?.Invoke() ?? 1; - /// - public override string SubFolder => _getSubFolderDelegate?.Invoke() ?? string.Empty; - /// - public override char SubGroupDelimiter => _getSubGroupDelimiterDelegate?.Invoke() ?? '/'; - /// - public override event PropertyChangedEventHandler? PropertyChanged - { - add { if (Object is INotifyPropertyChanged notifyPropertyChanged) notifyPropertyChanged.PropertyChanged += value; } - remove { if (Object is INotifyPropertyChanged notifyPropertyChanged) notifyPropertyChanged.PropertyChanged -= value; } - } - - protected BasePerSaveSettingsWrapper(object @object) - { - Object = @object; - var type = @object.GetType(); - - _getIdDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(Id)); - _getFolderNameDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(FolderName)); - _getDisplayNameDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(DisplayName)); - _getUIVersionDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(UIVersion)); - _getSubFolderDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(SubFolder)); - _getSubGroupDelimiterDelegate = AccessTools2.GetPropertyGetterDelegate(@object, type, nameof(SubGroupDelimiter)); - _methodOnPropertyChangedDelegate = AccessTools2.GetDelegate(@object, type, nameof(OnPropertyChanged)); - } - - /// - public override void OnPropertyChanged([CallerMemberName] string? propertyName = null) => - _methodOnPropertyChangedDelegate?.Invoke(propertyName); - } -} \ No newline at end of file diff --git a/src/MCM.Abstractions/Base/PerSave/FluentPerSaveSettings.cs b/src/MCM.Abstractions/Base/PerSave/FluentPerSaveSettings.cs index 16378e65..eede9ae0 100644 --- a/src/MCM.Abstractions/Base/PerSave/FluentPerSaveSettings.cs +++ b/src/MCM.Abstractions/Base/PerSave/FluentPerSaveSettings.cs @@ -56,7 +56,7 @@ public FluentPerSaveSettings(string id, string displayName, string folderName, s public void Register() { // TODO: check - var containers = GenericServiceProvider.GetService>() ?? Enumerable.Empty(); + var containers = GenericServiceProvider.GetService>() ?? []; foreach (var container in containers) { container?.Register(this); @@ -65,7 +65,7 @@ public void Register() public void Unregister() { // TODO: check - var containers = GenericServiceProvider.GetService>() ?? Enumerable.Empty(); + var containers = GenericServiceProvider.GetService>() ?? []; foreach (var container in containers) { container?.Unregister(this); diff --git a/src/MCM.Abstractions/Base/PerSave/PerSaveSettings.cs b/src/MCM.Abstractions/Base/PerSave/PerSaveSettings.cs index d1747be7..0e350b7e 100644 --- a/src/MCM.Abstractions/Base/PerSave/PerSaveSettings.cs +++ b/src/MCM.Abstractions/Base/PerSave/PerSaveSettings.cs @@ -25,7 +25,7 @@ public static T? Instance return BaseSettingsProvider.Instance?.GetSettings(Cache[typeof(T)]) as T; } } - + /* /// /// A modder flriendly way to get settings from any place diff --git a/src/MCM.Abstractions/Base/SettingsWrapper.cs b/src/MCM.Abstractions/Base/SettingsWrapper.cs index 3a09ca3a..340644cb 100644 --- a/src/MCM.Abstractions/Base/SettingsWrapper.cs +++ b/src/MCM.Abstractions/Base/SettingsWrapper.cs @@ -96,7 +96,7 @@ public override void OnPropertyChanged([CallerMemberName] string? propertyName = _methodOnPropertyChangedDelegate?.Invoke(propertyName); public override IEnumerable GetBuiltInPresets() => - _methodGetBuiltInPresetsDelegate?.Invoke()?.Cast().Select(CreatePreset).OfType() ?? Enumerable.Empty(); + _methodGetBuiltInPresetsDelegate?.Invoke()?.Cast().Select(CreatePreset).OfType() ?? []; public override BaseSettings CreateNew() => Create(_methodCreateNewDelegate?.Invoke()); public override BaseSettings CopyAsNew() => Create(_methodCopyAsNewDelegate?.Invoke()); diff --git a/src/MCM.Abstractions/Definitions/Attributes/v2/SettingPropertyGroupMetadataAttribute.cs b/src/MCM.Abstractions/Definitions/Attributes/v2/SettingPropertyGroupMetadataAttribute.cs new file mode 100644 index 00000000..bf92c612 --- /dev/null +++ b/src/MCM.Abstractions/Definitions/Attributes/v2/SettingPropertyGroupMetadataAttribute.cs @@ -0,0 +1,20 @@ +using System; + +// ReSharper disable once CheckNamespace +namespace MCM.Abstractions.Attributes.v2 +{ + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] +#if !BANNERLORDMCM_INCLUDE_IN_CODE_COVERAGE + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage, global::System.Diagnostics.DebuggerNonUserCode] +#endif +#if !BANNERLORDMCM_PUBLIC + internal +#else + public +# endif + sealed class SettingPropertyGroupMetadataAttribute : BaseSettingPropertyAttribute, + IPropertyDefinitionGroupMetadata + { + public SettingPropertyGroupMetadataAttribute() : base(string.Empty) { } + } +} \ No newline at end of file diff --git a/src/MCM.Abstractions/Definitions/IPropertyDefinitionGroupMetadata.cs b/src/MCM.Abstractions/Definitions/IPropertyDefinitionGroupMetadata.cs new file mode 100644 index 00000000..e15d3488 --- /dev/null +++ b/src/MCM.Abstractions/Definitions/IPropertyDefinitionGroupMetadata.cs @@ -0,0 +1,10 @@ +namespace MCM.Abstractions +{ +#if !BANNERLORDMCM_PUBLIC + internal +#else + public +# endif + interface IPropertyDefinitionGroupMetadata : IPropertyDefinitionBase + { } +} \ No newline at end of file diff --git a/src/MCM.Abstractions/Definitions/Wrapper/PropertyDefinitionGroupMetadataWrapper.cs b/src/MCM.Abstractions/Definitions/Wrapper/PropertyDefinitionGroupMetadataWrapper.cs new file mode 100644 index 00000000..a02efabb --- /dev/null +++ b/src/MCM.Abstractions/Definitions/Wrapper/PropertyDefinitionGroupMetadataWrapper.cs @@ -0,0 +1,15 @@ +namespace MCM.Abstractions.Wrapper +{ +#if !BANNERLORDMCM_INCLUDE_IN_CODE_COVERAGE + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage, global::System.Diagnostics.DebuggerNonUserCode] +#endif +#if !BANNERLORDMCM_PUBLIC + internal +#else + public +# endif + sealed class PropertyDefinitionGroupMetadataWrapper : BasePropertyDefinitionWrapper, IPropertyDefinitionGroupMetadata + { + public PropertyDefinitionGroupMetadataWrapper(object @object) : base(@object) { } + } +} \ No newline at end of file diff --git a/src/MCM.Abstractions/Definitions/Xml/PropertyDropdownXmlModel.cs b/src/MCM.Abstractions/Definitions/Xml/PropertyDropdownXmlModel.cs index c8b6d234..02f1b9f9 100644 --- a/src/MCM.Abstractions/Definitions/Xml/PropertyDropdownXmlModel.cs +++ b/src/MCM.Abstractions/Definitions/Xml/PropertyDropdownXmlModel.cs @@ -19,6 +19,6 @@ class PropertyDropdownXmlModel : PropertyBaseXmlModel, IPropertyDefinitionDropdo public int SelectedIndex { get; set; } [XmlArray("Values")] - public string[] Values { get; set; } = Array.Empty(); + public string[] Values { get; set; } = []; } } \ No newline at end of file diff --git a/src/MCM.Abstractions/Extensions/BaseSettingsExtensions.cs b/src/MCM.Abstractions/Extensions/BaseSettingsExtensions.cs index fa0b0d75..3c553a72 100644 --- a/src/MCM.Abstractions/Extensions/BaseSettingsExtensions.cs +++ b/src/MCM.Abstractions/Extensions/BaseSettingsExtensions.cs @@ -25,9 +25,9 @@ public static List GetSettingPropertyGroups(thi public static IEnumerable GetUnsortedSettingPropertyGroups(this BaseSettings settings) { - var discoverers = GenericServiceProvider.GetService>() ?? Enumerable.Empty(); + var discoverers = GenericServiceProvider.GetService>() ?? []; var discoverer = discoverers.FirstOrDefault(x => x.DiscoveryTypes.Any(y => y == settings.DiscoveryType)); - return SettingsUtils.GetSettingsPropertyGroups(settings.SubGroupDelimiter, discoverer?.GetProperties(settings) ?? Enumerable.Empty()); + return SettingsUtils.GetSettingsPropertyGroups(settings.SubGroupDelimiter, discoverer?.GetProperties(settings) ?? []); } public static IEnumerable GetAllSettingPropertyDefinitions(this BaseSettings settings) => @@ -36,6 +36,6 @@ public static IEnumerable GetAllSettingProperty settings.GetSettingPropertyGroups().SelectMany(SettingsUtils.GetAllSettingPropertyGroupDefinitions); public static IEnumerable GetExternalPresets(this BaseSettings settings) => - GenericServiceProvider.GetService()?.GetPresets(settings.Id) ?? Enumerable.Empty(); + GenericServiceProvider.GetService()?.GetPresets(settings.Id) ?? []; } } \ No newline at end of file diff --git a/src/MCM.Abstractions/Models/SettingsDefinition.cs b/src/MCM.Abstractions/Models/SettingsDefinition.cs index 4bab6735..09afe62e 100644 --- a/src/MCM.Abstractions/Models/SettingsDefinition.cs +++ b/src/MCM.Abstractions/Models/SettingsDefinition.cs @@ -22,7 +22,7 @@ public SettingsDefinition(string id) var settings = BaseSettingsProvider.Instance?.GetSettings(id); DisplayName = settings?.DisplayName ?? "ERROR"; - SettingPropertyGroups = settings?.GetSettingPropertyGroups() ?? new List(); + SettingPropertyGroups = settings?.GetSettingPropertyGroups() ?? []; } public SettingsDefinition(string id, string displayName, List settingsPropertyGroups) diff --git a/src/MCM.Abstractions/Models/SettingsPropertyDefinition.cs b/src/MCM.Abstractions/Models/SettingsPropertyDefinition.cs index bb79a858..1d98e2b4 100644 --- a/src/MCM.Abstractions/Models/SettingsPropertyDefinition.cs +++ b/src/MCM.Abstractions/Models/SettingsPropertyDefinition.cs @@ -22,7 +22,7 @@ sealed class SettingsPropertyDefinition : ISettingsPropertyDefinition /// public IRef PropertyReference { get; } /// - public SettingType SettingType { get; } + public SettingType SettingType { get; } = SettingType.NONE; /// public string DisplayName { get; } = string.Empty; /// diff --git a/src/MCM.Abstractions/Models/SettingsPropertyGroupDefinition.cs b/src/MCM.Abstractions/Models/SettingsPropertyGroupDefinition.cs index 9c653350..fb368739 100644 --- a/src/MCM.Abstractions/Models/SettingsPropertyGroupDefinition.cs +++ b/src/MCM.Abstractions/Models/SettingsPropertyGroupDefinition.cs @@ -1,7 +1,7 @@ using MCM.Common; -using System; using System.Collections.Generic; +using System.Linq; namespace MCM.Abstractions { @@ -33,8 +33,8 @@ private class DefaultPropertyGroupDefinition : IPropertyGroupDefinition protected readonly string _groupNameRaw; protected readonly string _groupNameOverrideRaw = string.Empty; - protected readonly List subGroups = new(); - protected readonly List settingProperties = new(); + protected readonly List subGroups = []; + protected readonly List settingProperties = []; protected char SubGroupDelimiter { get; set; } public SettingsPropertyGroupDefinition? Parent { get; set; } @@ -52,18 +52,13 @@ public string DisplayGroupNameRaw } } - public int Order { get; } + public int Order { get; private set; } public IEnumerable SubGroups => subGroups.SortDefault(); public IEnumerable SettingProperties => settingProperties.SortDefault(); - public SettingsPropertyGroupDefinition(string groupName, int order = -1) - { - _groupNameRaw = groupName; - Order = order; - } + public bool IsEmpty => !SubGroups.Any() && SettingProperties.All(x => x.SettingType == SettingType.NONE); - [Obsolete("Override not needed", true)] - public SettingsPropertyGroupDefinition(string groupName, string? _, int order = -1) + public SettingsPropertyGroupDefinition(string groupName, int order = -1) { _groupNameRaw = groupName; Order = order; @@ -91,8 +86,6 @@ public void Add(SettingsPropertyGroupDefinition settingProp) } public SettingsPropertyGroupDefinition? GetGroup(string groupName) => subGroups.GetGroupFromName(groupName); - [Obsolete("Use GetGroup", true)] - public SettingsPropertyGroupDefinition? GetGroupFor(string groupName) => subGroups.GetGroupFromName(groupName); /// public override string ToString() => GroupName; diff --git a/src/MCM.Abstractions/Properties/NoneSettingsPropertyDiscoverer.cs b/src/MCM.Abstractions/Properties/NoneSettingsPropertyDiscoverer.cs index 538f5d97..ef1f8eee 100644 --- a/src/MCM.Abstractions/Properties/NoneSettingsPropertyDiscoverer.cs +++ b/src/MCM.Abstractions/Properties/NoneSettingsPropertyDiscoverer.cs @@ -14,6 +14,6 @@ sealed class NoneSettingsPropertyDiscoverer : ISettingsPropertyDiscoverer { public IEnumerable DiscoveryTypes { get; } = new[] { "none" }; - public IEnumerable GetProperties(BaseSettings settings) => Enumerable.Empty(); + public IEnumerable GetProperties(BaseSettings settings) => []; } } \ No newline at end of file diff --git a/src/MCM.Abstractions/Providers/SettingsProviderWrapper.cs b/src/MCM.Abstractions/Providers/SettingsProviderWrapper.cs index dac70621..e5df12d0 100644 --- a/src/MCM.Abstractions/Providers/SettingsProviderWrapper.cs +++ b/src/MCM.Abstractions/Providers/SettingsProviderWrapper.cs @@ -34,7 +34,7 @@ abstract class SettingsProviderWrapper : BaseSettingsProvider, IWrapper private readonly ResetSettingsDelegate? _methodResetSettingsDelegate; public override IEnumerable SettingsDefinitions => - _methodGetSettingsDefinitions?.Invoke().Cast().Select(x => new SettingsDefinitionWrapper(x)) ?? Enumerable.Empty(); + _methodGetSettingsDefinitions?.Invoke().Cast().Select(x => new SettingsDefinitionWrapper(x)) ?? []; /// public object Object { get; } diff --git a/src/MCM.Abstractions/SettingType.cs b/src/MCM.Abstractions/SettingType.cs index 42250903..2d11a716 100644 --- a/src/MCM.Abstractions/SettingType.cs +++ b/src/MCM.Abstractions/SettingType.cs @@ -6,7 +6,7 @@ namespace MCM.Abstractions /// Defines the different types of settings that can be used. /// #if !BANNERLORDMCM_PUBLIC - internal + internal #else public #endif diff --git a/src/MCM.Abstractions/Utils/SettingsUtils.cs b/src/MCM.Abstractions/Utils/SettingsUtils.cs index 2b41bfc6..27e4abb5 100644 --- a/src/MCM.Abstractions/Utils/SettingsUtils.cs +++ b/src/MCM.Abstractions/Utils/SettingsUtils.cs @@ -337,6 +337,10 @@ public static IEnumerable GetPropertyDefinitionWrappers propAttr = properties.SingleOrDefault(a => a is IPropertyDefinitionButton); if (propAttr is not null) yield return new PropertyDefinitionButtonWrapper(propAttr); + + propAttr = properties.SingleOrDefault(a => a is IPropertyDefinitionGroupMetadata); + if (propAttr is not null) + yield return new PropertyDefinitionGroupMetadataWrapper(propAttr); } } } \ No newline at end of file diff --git a/src/MCM.Bannerlord/GameFeatures/FileSystemProvider.cs b/src/MCM.Bannerlord/GameFeatures/FileSystemProvider.cs index d2b24309..4b388500 100644 --- a/src/MCM.Bannerlord/GameFeatures/FileSystemProvider.cs +++ b/src/MCM.Bannerlord/GameFeatures/FileSystemProvider.cs @@ -60,7 +60,7 @@ public GameFile GetOrCreateFile(GameDirectory directory, string fileName) var file = new TWPlatformFilePath(new TWPlatformDirectoryPath((PlatformFileType) directory.Type, directory.Path), fileName); if (!PlatformFileHelper.FileExists(file)) { - PlatformFileHelper.SaveFile(file, Array.Empty()); + PlatformFileHelper.SaveFile(file, []); } return new GameFile(directory, fileName); } diff --git a/src/MCM.Common/Dropdown.cs b/src/MCM.Common/Dropdown.cs index a8dca4fa..88c4cb5f 100644 --- a/src/MCM.Common/Dropdown.cs +++ b/src/MCM.Common/Dropdown.cs @@ -17,7 +17,7 @@ namespace MCM.Common # endif sealed class Dropdown : List, IEqualityComparer>, INotifyPropertyChanged, ICloneable { - public static Dropdown Empty => new(Enumerable.Empty(), 0); + public static Dropdown Empty => new([], 0); private int _selectedIndex; private T? _selectedValue; diff --git a/src/MCM.Common/Ref/ProxyRef.cs b/src/MCM.Common/Ref/ProxyRef.cs index cbb44ee2..a575466d 100644 --- a/src/MCM.Common/Ref/ProxyRef.cs +++ b/src/MCM.Common/Ref/ProxyRef.cs @@ -25,6 +25,7 @@ class ProxyRef : IRef, IEquatable> /// public Type Type => typeof(T); + /// public object? Value { diff --git a/src/MCM.Common/Utils/LocalizationUtils.cs b/src/MCM.Common/Utils/LocalizationUtils.cs index dbfe2c6d..458a16a1 100644 --- a/src/MCM.Common/Utils/LocalizationUtils.cs +++ b/src/MCM.Common/Utils/LocalizationUtils.cs @@ -19,7 +19,7 @@ private readonly ref struct TextObjectWrapper { private delegate object TextObjectCtorDelegate(string rawText, Dictionary? attributes = null); private static readonly TextObjectCtorDelegate? _textObjectCtor = - AccessTools2.GetDeclaredConstructorDelegate("TaleWorlds.Localization.TextObject", new[] { typeof(string), typeof(Dictionary) }); + AccessTools2.GetDeclaredConstructorDelegate("TaleWorlds.Localization.TextObject", [typeof(string), typeof(Dictionary)]); private delegate string? ToStringDelegate(object instance); private static readonly ToStringDelegate? _toString = diff --git a/src/MCM.Implementation/Containers/BaseSettingsContainer.cs b/src/MCM.Implementation/Containers/BaseSettingsContainer.cs index 23f6f162..e74b9b7f 100644 --- a/src/MCM.Implementation/Containers/BaseSettingsContainer.cs +++ b/src/MCM.Implementation/Containers/BaseSettingsContainer.cs @@ -48,7 +48,7 @@ protected virtual void RegisterSettings(TSettings? settings) var folderDirectory = fileSystemProvider.GetOrCreateDirectory(RootFolder, settings.FolderName); var directory = string.IsNullOrEmpty(settings.SubFolder) ? folderDirectory : fileSystemProvider.GetOrCreateDirectory(folderDirectory, settings.SubFolder); - var settingsFormats = GenericServiceProvider.GetService>() ?? Enumerable.Empty(); + var settingsFormats = GenericServiceProvider.GetService>() ?? []; var settingsFormat = settingsFormats.FirstOrDefault(x => x.FormatTypes.Any(y => y == settings.FormatType)); settingsFormat?.Load(settings, directory, settings.Id); settings.OnPropertyChanged(BaseSettings.LoadingComplete); @@ -68,7 +68,7 @@ public virtual bool SaveSettings(BaseSettings settings) var folderDirectory = fileSystemProvider.GetOrCreateDirectory(RootFolder, settings.FolderName); var directory = string.IsNullOrEmpty(settings.SubFolder) ? folderDirectory : fileSystemProvider.GetOrCreateDirectory(folderDirectory, settings.SubFolder); - var settingsFormats = GenericServiceProvider.GetService>() ?? Enumerable.Empty(); + var settingsFormats = GenericServiceProvider.GetService>() ?? []; var settingsFormat = settingsFormats.FirstOrDefault(x => x.FormatTypes.Any(y => y == settings.FormatType)); settingsFormat?.Save(settings, directory, settings.Id); diff --git a/src/MCM.Implementation/Containers/Global/ExternalGlobalSettingsContainer.cs b/src/MCM.Implementation/Containers/Global/ExternalGlobalSettingsContainer.cs index 509fb4e8..a7b93ed0 100644 --- a/src/MCM.Implementation/Containers/Global/ExternalGlobalSettingsContainer.cs +++ b/src/MCM.Implementation/Containers/Global/ExternalGlobalSettingsContainer.cs @@ -38,7 +38,7 @@ public bool SaveSettings(BaseSettings settings) /* var directoryPath = Path.Combine(RootFolder, settings.FolderName, settings.SubFolder); - var settingsFormats = GenericServiceProvider.GetService>() ?? Enumerable.Empty(); + var settingsFormats = GenericServiceProvider.GetService>() ?? []; var settingsFormat = settingsFormats.FirstOrDefault(x => x.FormatTypes.Any(y => y == settings.FormatType)); settingsFormat?.Save(settings, directoryPath, settings.Id); */ diff --git a/src/MCM.Implementation/Containers/Global/GlobalSettingsContainer.cs b/src/MCM.Implementation/Containers/Global/GlobalSettingsContainer.cs index 1987a4f1..731af6be 100644 --- a/src/MCM.Implementation/Containers/Global/GlobalSettingsContainer.cs +++ b/src/MCM.Implementation/Containers/Global/GlobalSettingsContainer.cs @@ -56,7 +56,7 @@ IEnumerable GetGlobalSettings() } catch (TypeLoadException ex) { - settings = Array.Empty(); + settings = []; logger.LogError(ex, $"Error while handling assembly {assembly}!"); } diff --git a/src/MCM.Implementation/Containers/PerCampaign/PerCampaignSettingsContainer.cs b/src/MCM.Implementation/Containers/PerCampaign/PerCampaignSettingsContainer.cs index e558c822..2599b152 100644 --- a/src/MCM.Implementation/Containers/PerCampaign/PerCampaignSettingsContainer.cs +++ b/src/MCM.Implementation/Containers/PerCampaign/PerCampaignSettingsContainer.cs @@ -147,7 +147,7 @@ private IEnumerable GetPerCampaignSettings() } catch (TypeLoadException ex) { - settings = Array.Empty(); + settings = []; _logger.LogError(ex, $"Error while handling assembly {assembly}!"); } diff --git a/src/MCM.Implementation/Containers/PerSave/FluentPerSaveSettingsContainer.cs b/src/MCM.Implementation/Containers/PerSave/FluentPerSaveSettingsContainer.cs index 0b1f168d..60ad5c6b 100644 --- a/src/MCM.Implementation/Containers/PerSave/FluentPerSaveSettingsContainer.cs +++ b/src/MCM.Implementation/Containers/PerSave/FluentPerSaveSettingsContainer.cs @@ -87,6 +87,6 @@ public void LoadSettings() { } public void GameEnded() => LoadedSettings.Clear(); /// - public IEnumerable GetUnavailableSettings() => Enumerable.Empty(); + public IEnumerable GetUnavailableSettings() => []; } } \ No newline at end of file diff --git a/src/MCM.Implementation/Containers/PerSave/PerSaveSettingsContainer.cs b/src/MCM.Implementation/Containers/PerSave/PerSaveSettingsContainer.cs index f2622a82..1e9db2b4 100644 --- a/src/MCM.Implementation/Containers/PerSave/PerSaveSettingsContainer.cs +++ b/src/MCM.Implementation/Containers/PerSave/PerSaveSettingsContainer.cs @@ -119,7 +119,7 @@ private IEnumerable GetPerSaveSettings() } catch (TypeLoadException ex) { - settings = Array.Empty(); + settings = []; _logger.LogError(ex, $"Error while handling assembly {assembly}!"); } @@ -136,7 +136,7 @@ public void LoadSettings() public IEnumerable GetUnavailableSettings() => !_hasGameStarted ? GetPerSaveSettings().Select(setting => new UnavailableSetting(setting.Id, setting.DisplayName, UnavailableSettingType.PerSave)) - : Enumerable.Empty(); + : []; private void GameEnded() { diff --git a/src/MCM.Implementation/FluentBuilder/DefaultSettingsBuilder.cs b/src/MCM.Implementation/FluentBuilder/DefaultSettingsBuilder.cs index 489c846a..3150fecb 100644 --- a/src/MCM.Implementation/FluentBuilder/DefaultSettingsBuilder.cs +++ b/src/MCM.Implementation/FluentBuilder/DefaultSettingsBuilder.cs @@ -5,6 +5,7 @@ using MCM.Abstractions.Base.PerSave; using MCM.Abstractions.FluentBuilder; using MCM.Abstractions.Wrapper; +using MCM.Common; using System; using System.Collections.Generic; @@ -127,10 +128,17 @@ private IEnumerable GetSettingProperties() { foreach (var settingsPropertyGroup in PropertyGroups.Values) { + var groupDefinition = settingsPropertyGroup.GetPropertyGroupDefinition(); + + yield return new SettingsPropertyDefinition([new PropertyDefinitionGroupMetadataWrapper(new { DisplayName = "", Order = 0, RequireRestart = false, HintText = "" })], + new PropertyGroupDefinitionWrapper(groupDefinition), + new StorageRef(new()), + SubGroupDelimiter); + foreach (var settingsProperty in settingsPropertyGroup.Properties.Values) { yield return new SettingsPropertyDefinition(settingsProperty.GetDefinitions(), - new PropertyGroupDefinitionWrapper(settingsPropertyGroup.GetPropertyGroupDefinition()), + new PropertyGroupDefinitionWrapper(groupDefinition), settingsProperty.PropertyReference, SubGroupDelimiter); } diff --git a/src/MCM.Implementation/Properties/FluentSettingsPropertyDiscoverer.cs b/src/MCM.Implementation/Properties/FluentSettingsPropertyDiscoverer.cs index 03f2c65a..3391a190 100644 --- a/src/MCM.Implementation/Properties/FluentSettingsPropertyDiscoverer.cs +++ b/src/MCM.Implementation/Properties/FluentSettingsPropertyDiscoverer.cs @@ -22,7 +22,7 @@ internal sealed class FluentSettingsPropertyDiscoverer : IFluentSettingsProperty public IEnumerable GetProperties(BaseSettings settings) { var settingPropertyGroups = _getSettingPropertyGroups?.Invoke(settings) - .Select(x => new SettingsPropertyGroupDefinitionWrapper(x)).Cast().ToList() ?? new List(); + .Select(x => new SettingsPropertyGroupDefinitionWrapper(x)).Cast().ToList() ?? []; return settingPropertyGroups.SelectMany(SettingsUtils.GetAllSettingPropertyDefinitions); } diff --git a/src/MCM.Implementation/Providers/DefaultSettingsProvider.cs b/src/MCM.Implementation/Providers/DefaultSettingsProvider.cs index 4bc31700..262e0007 100644 --- a/src/MCM.Implementation/Providers/DefaultSettingsProvider.cs +++ b/src/MCM.Implementation/Providers/DefaultSettingsProvider.cs @@ -33,13 +33,13 @@ public DefaultSettingsProvider(IBUTRLogger logger) _logger = logger; var globalSettingsContainers = (GenericServiceProvider.GetService>() ?? - Enumerable.Empty()).ToList(); + []).ToList(); var perSaveSettingsContainers = (GenericServiceProvider.GetService>() ?? - Enumerable.Empty()).ToList(); + []).ToList(); var perCampaignSettingsContainers = (GenericServiceProvider.GetService>() ?? - Enumerable.Empty()).ToList(); + []).ToList(); var externalSettingsProviders = (GenericServiceProvider.GetService>() ?? - Enumerable.Empty()).ToList(); + []).ToList(); foreach (var globalSettingsContainer in globalSettingsContainers) { @@ -48,6 +48,7 @@ public DefaultSettingsProvider(IBUTRLogger logger) logger.LogInformation($"Found Global container {globalSettingsContainer.GetType()} ({globalSettingsContainer.SettingsDefinitions.Count()})"); } + foreach (var perSaveSettingsContainer in perSaveSettingsContainers) { if (perSaveSettingsContainer is ISettingsContainerCanInvalidateCache canInvalidateCache) @@ -55,6 +56,7 @@ public DefaultSettingsProvider(IBUTRLogger logger) logger.LogInformation($"Found PerSave container {perSaveSettingsContainer.GetType()} ({perSaveSettingsContainer.SettingsDefinitions.Count()})"); } + foreach (var perCampaignSettingsContainer in perCampaignSettingsContainers) { if (perCampaignSettingsContainer is ISettingsContainerCanInvalidateCache canInvalidateCache) @@ -62,6 +64,7 @@ public DefaultSettingsProvider(IBUTRLogger logger) logger.LogInformation($"Found Campaign container {perCampaignSettingsContainer.GetType()} ({perCampaignSettingsContainer.SettingsDefinitions.Count()})"); } + foreach (var externalSettingsProvider in externalSettingsProviders) { if (externalSettingsProvider is IExternalSettingsProviderCanInvalidateCache canInvalidateCache) @@ -104,6 +107,7 @@ public DefaultSettingsProvider(IBUTRLogger logger) return settings; } } + foreach (var settingsProvider in _externalSettingsProviders) { if (settingsProvider.GetSettings(id) is { } settings) @@ -111,6 +115,7 @@ public DefaultSettingsProvider(IBUTRLogger logger) return settings; } } + _logger.LogWarning($"GetSettings {id} returned null"); return null; } @@ -150,6 +155,7 @@ public override IEnumerable GetPresets(string id) yield return preset; } } + foreach (var settingsProvider in _externalSettingsProviders) { foreach (var preset in settingsProvider.GetPresets(id)) diff --git a/src/MCM.UI.Adapter.MCMv5/Properties/MCMv5FluentSettingsPropertyDiscoverer.cs b/src/MCM.UI.Adapter.MCMv5/Properties/MCMv5FluentSettingsPropertyDiscoverer.cs index 6f6a1409..f87b8d41 100644 --- a/src/MCM.UI.Adapter.MCMv5/Properties/MCMv5FluentSettingsPropertyDiscoverer.cs +++ b/src/MCM.UI.Adapter.MCMv5/Properties/MCMv5FluentSettingsPropertyDiscoverer.cs @@ -32,7 +32,7 @@ public IEnumerable GetProperties(BaseSettings setti var del = _cache.GetOrAdd(obj.GetType(), static x => AccessTools2.GetPropertyGetterDelegate(x, "SettingPropertyGroups")); var settingPropertyGroups = del?.Invoke(obj)?.Cast() - .Select(x => new SettingsPropertyGroupDefinitionWrapper(x)).Cast().ToList() ?? new List(); + .Select(x => new SettingsPropertyGroupDefinitionWrapper(x)).Cast().ToList() ?? []; return settingPropertyGroups.SelectMany(SettingsUtils.GetAllSettingPropertyDefinitions); } diff --git a/src/MCM.UI.Adapter.MCMv5/Providers/MCMv5ExternalSettingsProvider.cs b/src/MCM.UI.Adapter.MCMv5/Providers/MCMv5ExternalSettingsProvider.cs index 9fefcdf5..811a702e 100644 --- a/src/MCM.UI.Adapter.MCMv5/Providers/MCMv5ExternalSettingsProvider.cs +++ b/src/MCM.UI.Adapter.MCMv5/Providers/MCMv5ExternalSettingsProvider.cs @@ -14,7 +14,7 @@ namespace MCM.UI.Adapter.MCMv5.Providers internal sealed class MCMv5ExternalSettingsProvider : IExternalSettingsProvider, IExternalSettingsProviderHasInitialize { private readonly IBUTRLogger _logger; - private readonly List _settingsProviderWrappers = new(); + private readonly List _settingsProviderWrappers = []; public IEnumerable SettingsDefinitions => _settingsProviderWrappers .SelectMany(x => x.SettingsDefinitions) diff --git a/src/MCM.UI.Adapter.MCMv5/Providers/MCMv5SettingsProviderWrapper.cs b/src/MCM.UI.Adapter.MCMv5/Providers/MCMv5SettingsProviderWrapper.cs index 96be1814..1467f565 100644 --- a/src/MCM.UI.Adapter.MCMv5/Providers/MCMv5SettingsProviderWrapper.cs +++ b/src/MCM.UI.Adapter.MCMv5/Providers/MCMv5SettingsProviderWrapper.cs @@ -63,7 +63,7 @@ public override IEnumerable GetPresets(string settingsId) { var settings = GetSettings(settingsId); if (settings is not MCMv5AttributeSettingsWrapper or MCMv5FluentSettingsWrapper || settings is not IWrapper { Object: { } obj } || _methodGetPresetsDelegate is null) - return Enumerable.Empty(); + return []; var type = obj.GetType(); var presets = _methodGetPresetsDelegate.Invoke(settingsId).OfType(); @@ -83,13 +83,13 @@ public override IEnumerable GetPresets(string settingsId) if (ReflectionUtils.ImplementsOrImplementsEquivalent(type, "MCM.Abstractions.Base.PerSave.PerSaveSettings")) return presets.Select(x => new MCMv5AttributeSettingsPresetWrapper(x)); - return Enumerable.Empty(); + return []; } - public override IEnumerable GetUnavailableSettings() => Enumerable.Empty(); + public override IEnumerable GetUnavailableSettings() => []; - public override IEnumerable SaveAvailableSnapshots() => Enumerable.Empty(); + public override IEnumerable SaveAvailableSnapshots() => []; - public override IEnumerable LoadAvailableSnapshots(IEnumerable snapshots) => Enumerable.Empty(); + public override IEnumerable LoadAvailableSnapshots(IEnumerable snapshots) => []; } } \ No newline at end of file diff --git a/src/MCM.UI.Adapter.MCMv5/SubModule.cs b/src/MCM.UI.Adapter.MCMv5/SubModule.cs index 81806428..39179cbe 100644 --- a/src/MCM.UI.Adapter.MCMv5/SubModule.cs +++ b/src/MCM.UI.Adapter.MCMv5/SubModule.cs @@ -21,7 +21,7 @@ public sealed class SubModule : MBSubModuleBase private static void OnAfterSetInitialModuleScreenAsRootScreen() { var enumerable = GenericServiceProvider.GetService>()?.OfType() ?? - Enumerable.Empty(); + []; foreach (var hasInitialize in enumerable) hasInitialize.Initialize(); diff --git a/src/MCM.UI/Actions/ComplexValueTypeAction.cs b/src/MCM.UI/Actions/ComplexValueTypeAction.cs index 9bcea798..f9b7f2c7 100644 --- a/src/MCM.UI/Actions/ComplexValueTypeAction.cs +++ b/src/MCM.UI/Actions/ComplexValueTypeAction.cs @@ -12,17 +12,6 @@ internal sealed class ComplexValueTypeAction : IAction where T : struct private Func DoFunction { get; } private Func UndoFunction { get; } - /// - /// new ProxyRef(() => ValueType, o => ValueType = o) - /// - [Obsolete("Use the nullable overload instead!", true)] - public ComplexValueTypeAction(IRef context, Func doFunction, Func undoFunction) - { - Context = context; - DoFunction = (obj) => obj; - UndoFunction = (obj) => obj; - } - /// /// new ProxyRef(() => ValueType, o => ValueType = o) /// diff --git a/src/MCM.UI/ButterLib/LoggerWrapper.cs b/src/MCM.UI/ButterLib/LoggerWrapper.cs index f332cc92..44f036a1 100644 --- a/src/MCM.UI/ButterLib/LoggerWrapper.cs +++ b/src/MCM.UI/ButterLib/LoggerWrapper.cs @@ -16,9 +16,9 @@ namespace MCM.UI.ButterLib internal class LogValuesFormatter { private const string NullValue = "(null)"; - private static readonly object[] EmptyArray = Array.Empty(); + private static readonly object[] EmptyArray = []; private readonly string _format; - private readonly List _valueNames = new(); + private readonly List _valueNames = []; public LogValuesFormatter(string format) { diff --git a/src/MCM.UI/ComparerExtensions/CompoundComparer.cs b/src/MCM.UI/ComparerExtensions/CompoundComparer.cs index 28800727..956675f5 100644 --- a/src/MCM.UI/ComparerExtensions/CompoundComparer.cs +++ b/src/MCM.UI/ComparerExtensions/CompoundComparer.cs @@ -17,7 +17,7 @@ public static IComparer GetComparer(IComparer baseComparer, IComparer n public CompoundComparer() { - _comparers = new List>(); + _comparers = []; } public void AppendComparison(IComparer comparer) diff --git a/src/MCM.UI/Dropdown/MCMSelectorVM.cs b/src/MCM.UI/Dropdown/MCMSelectorVM.cs index d235a6f6..6f00645b 100644 --- a/src/MCM.UI/Dropdown/MCMSelectorVM.cs +++ b/src/MCM.UI/Dropdown/MCMSelectorVM.cs @@ -26,7 +26,7 @@ internal class MCMSelectorVM : ViewModel where TSelectorItemVM private bool _hasSingleItem; [DataSourceProperty] - public MBBindingList ItemList { get; } = new(); + public MBBindingList ItemList { get; } = []; [DataSourceProperty] public int SelectedIndex diff --git a/src/MCM.UI/Extensions/SettingsBuilderExtensions.cs b/src/MCM.UI/Extensions/SettingsBuilderExtensions.cs index 1dc41711..34b85f20 100644 --- a/src/MCM.UI/Extensions/SettingsBuilderExtensions.cs +++ b/src/MCM.UI/Extensions/SettingsBuilderExtensions.cs @@ -87,7 +87,7 @@ public static ISettingsBuilder AddButterLibSubSystems(this ISettingsBuilder sett if (subSystemType.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ISubSystemSettings<>))) { var method = AccessTools2.DeclaredMethod(typeof(SettingsBuilderExtensions), "AddForSubSystem")?.MakeGenericMethod(subSystemType); - method?.Invoke(null, new object[] { subSystem, settings }); + method?.Invoke(null, [subSystem, settings]); } } return settings; diff --git a/src/MCM.UI/GUI/ViewModels/ModOptionsVM.cs b/src/MCM.UI/GUI/ViewModels/ModOptionsVM.cs index cc2a06ab..1d14e4a1 100644 --- a/src/MCM.UI/GUI/ViewModels/ModOptionsVM.cs +++ b/src/MCM.UI/GUI/ViewModels/ModOptionsVM.cs @@ -74,7 +74,7 @@ private SettingsEntryVM? SelectedEntry } else { - PresetsSelectorCopy.Refresh(Enumerable.Empty(), -1); + PresetsSelectorCopy.Refresh([], -1); } }); OnPropertyChanged(nameof(IsPresetsSelectorVisible)); @@ -98,7 +98,7 @@ private SettingsEntryVM? SelectedEntry [DataSourceProperty] public string ModsText { get => _modsText; set => SetField(ref _modsText, value, nameof(ModsText)); } [DataSourceProperty] - public MBBindingList ModSettingsList { get; } = new(); + public MBBindingList ModSettingsList { get; } = []; [DataSourceProperty] public SettingsVM? SelectedMod => SelectedEntry?.SettingsVM; [DataSourceProperty] @@ -188,7 +188,7 @@ private void InitializeModSettings() }) .Where(vm => vm is not null); - foreach (var viewModel in settingsVM ?? Enumerable.Empty()) + foreach (var viewModel in settingsVM ?? []) { uiContext.Send(state => { @@ -201,7 +201,7 @@ private void InitializeModSettings() } // TODO: We are not able to show Fluent PerSave/Campaign settings this way. For now, don't use it - //foreach (var unavailableSetting in BaseSettingsProvider.Instance?.GetUnavailableSettings() ?? Enumerable.Empty()) + //foreach (var unavailableSetting in BaseSettingsProvider.Instance?.GetUnavailableSettings() ?? []) // ModSettingsList.Add(new SettingsEntryVM(unavailableSetting, ExecuteSelect)); // Yea, I imported a whole library that converts LINQ style order to IComparer @@ -653,7 +653,7 @@ void ImportPack() snapshots.Add(new SettingSnapshot(entry.FullName, reader.ReadToEnd())); } - foreach (var settings in BaseSettingsProvider.Instance?.LoadAvailableSnapshots(snapshots) ?? Enumerable.Empty()) + foreach (var settings in BaseSettingsProvider.Instance?.LoadAvailableSnapshots(snapshots) ?? []) { if (ModSettingsList.FirstOrDefault(x => x.Id == settings.Id) is not { SettingsVM: { SettingsInstance: { } current } viewModel }) continue; UISettingsUtils.OverrideValues(viewModel.URS, current, settings); @@ -677,7 +677,7 @@ void ExportPack() }; if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { - var snapshots = BaseSettingsProvider.Instance?.SaveAvailableSnapshots() ?? Enumerable.Empty(); + var snapshots = BaseSettingsProvider.Instance?.SaveAvailableSnapshots() ?? []; using var file = File.Create(dialog.FileName); using var archive = new ZipArchive(file, ZipArchiveMode.Create); foreach (var snapshot in snapshots) @@ -710,11 +710,10 @@ void OnActionSelected(List selected) MBInformationManager.ShowMultiSelectionInquiry(InquiryDataUtils.CreateMultiTranslatable( "{=ModOptionsVM_ManagePacks}Manage Settings Packs", "", - new List - { + [ new(importPack, new TextObject("{=ModOptionsVM_ManagePackImport}Import a Settings Pack").ToString(), null), - new(exportPack, new TextObject("{=ModOptionsVM_ManagePackExport}Export Settings Pack").ToString(), null), - }, + new(exportPack, new TextObject("{=ModOptionsVM_ManagePackExport}Export Settings Pack").ToString(), null) + ], true, 1, 1, "{=5Unqsx3N}Confirm", diff --git a/src/MCM.UI/GUI/ViewModels/SettingsPropertyGroupVM.cs b/src/MCM.UI/GUI/ViewModels/SettingsPropertyGroupVM.cs index 938179e1..6a3d48a1 100644 --- a/src/MCM.UI/GUI/ViewModels/SettingsPropertyGroupVM.cs +++ b/src/MCM.UI/GUI/ViewModels/SettingsPropertyGroupVM.cs @@ -43,9 +43,9 @@ public bool SatisfiesSearch [DataSourceProperty] public string GroupNameDisplay { get => _groupNameDisplay; set => SetField(ref _groupNameDisplay, value, nameof(GroupNameDisplay)); } [DataSourceProperty] - public MBBindingList SettingProperties { get; } = new(); + public MBBindingList SettingProperties { get; } = []; [DataSourceProperty] - public MBBindingList SettingPropertyGroups { get; } = new(); + public MBBindingList SettingPropertyGroups { get; } = []; [DataSourceProperty] public bool GroupToggle { @@ -114,8 +114,8 @@ public SettingsPropertyGroupVM(SettingsPropertyGroupDefinition definition, Setti SettingPropertyGroupDefinition = definition; ParentGroup = parentGroup; - AddRange(SettingPropertyGroupDefinition.SettingProperties); - SettingPropertyGroups.AddRange(SettingPropertyGroupDefinition.SubGroups.Select(x => new SettingsPropertyGroupVM(x, SettingsVM, this))); + AddRange(SettingPropertyGroupDefinition.SettingProperties.Where(x => x.SettingType != SettingType.NONE)); + SettingPropertyGroups.AddRange(SettingPropertyGroupDefinition.SubGroups.Where(x => !x.IsEmpty).Select(x => new SettingsPropertyGroupVM(x, SettingsVM, this))); RefreshValues(); } diff --git a/src/MCM.UI/GUI/ViewModels/SettingsVM.cs b/src/MCM.UI/GUI/ViewModels/SettingsVM.cs index 3fed11c3..ea194a04 100644 --- a/src/MCM.UI/GUI/ViewModels/SettingsVM.cs +++ b/src/MCM.UI/GUI/ViewModels/SettingsVM.cs @@ -24,14 +24,14 @@ internal sealed class SettingsVM : ViewModel public SettingsDefinition SettingsDefinition { get; } public BaseSettings? SettingsInstance => BaseSettingsProvider.Instance?.GetSettings(SettingsDefinition.SettingsId); - public MCMSelectorVM> PresetsSelector { get; } = new(Enumerable.Empty>(), -1); + public MCMSelectorVM> PresetsSelector { get; } = new([], -1); [DataSourceProperty] public string DisplayName { get => _displayName; private set => SetField(ref _displayName, value, nameof(DisplayName)); } [DataSourceProperty] public bool IsSelected { get => _isSelected; set => SetField(ref _isSelected, value, nameof(IsSelected)); } [DataSourceProperty] - public MBBindingList SettingPropertyGroups { get; } = new(); + public MBBindingList SettingPropertyGroups { get; } = []; public SettingsVM(SettingsDefinition definition, ModOptionsVM mainView) { @@ -41,7 +41,7 @@ public SettingsVM(SettingsDefinition definition, ModOptionsVM mainView) ReloadPresetList(); if (SettingsInstance is not null) - SettingPropertyGroups.AddRange(SettingPropertyDefinitionCache.GetSettingPropertyGroups(SettingsInstance).Select(x => new SettingsPropertyGroupVM(x, this))); + SettingPropertyGroups.AddRange(SettingPropertyDefinitionCache.GetSettingPropertyGroups(SettingsInstance).Where(x => !x.IsEmpty).Select(x => new SettingsPropertyGroupVM(x, this))); RefreshValues(); } @@ -49,7 +49,7 @@ public SettingsVM(SettingsDefinition definition, ModOptionsVM mainView) public void ReloadPresetList() { _cachedPresets.Clear(); - foreach (var preset in SettingsInstance?.GetBuiltInPresets().Concat(SettingsInstance.GetExternalPresets()) ?? Enumerable.Empty()) + foreach (var preset in SettingsInstance?.GetBuiltInPresets().Concat(SettingsInstance.GetExternalPresets()) ?? []) _cachedPresets.Add(new PresetKey(preset), preset.LoadPreset()); var presets = new List { new("custom", "{=SettingsVM_Custom}Custom") }.Concat(_cachedPresets.Keys); diff --git a/src/MCM.UI/MCM.UI.csproj b/src/MCM.UI/MCM.UI.csproj index b05713b6..ac7d2c11 100644 --- a/src/MCM.UI/MCM.UI.csproj +++ b/src/MCM.UI/MCM.UI.csproj @@ -10,6 +10,7 @@ $(DefineConstants) true true + latest diff --git a/src/MCM.UI/UIExtenderEx/OptionsPrefabExtensions.cs b/src/MCM.UI/UIExtenderEx/OptionsPrefabExtensions.cs index 918af1f8..344a02b2 100644 --- a/src/MCM.UI/UIExtenderEx/OptionsPrefabExtensions.cs +++ b/src/MCM.UI/UIExtenderEx/OptionsPrefabExtensions.cs @@ -41,9 +41,6 @@ public OptionsPrefabExtension2() [PrefabExtension("Options", "descendant::Widget[@Id='DescriptionsRightPanel']", "Options")] internal sealed class OptionsPrefabExtension3 : PrefabExtensionSetAttributePatch { - public override List Attributes => new() - { - new Attribute("SuggestedWidth", "@DescriptionWidth") - }; + public override List Attributes => [new Attribute("SuggestedWidth", "@DescriptionWidth")]; } } \ No newline at end of file diff --git a/src/MCM.UI/UIExtenderEx/OptionsVMMixin.cs b/src/MCM.UI/UIExtenderEx/OptionsVMMixin.cs index a058f683..7afc863f 100644 --- a/src/MCM.UI/UIExtenderEx/OptionsVMMixin.cs +++ b/src/MCM.UI/UIExtenderEx/OptionsVMMixin.cs @@ -116,7 +116,7 @@ public bool ModOptionsSelected public OptionsVMMixin(OptionsVM vm) : base(vm) { vm.PropertyChanged += OptionsVM_PropertyChanged; - var list = _categories?.Invoke(vm) ?? new List(); + var list = _categories?.Invoke(vm) ?? []; list.Insert(5, _modOptions); } diff --git a/src/MCM.UI/Utils/UISettingsUtils.cs b/src/MCM.UI/Utils/UISettingsUtils.cs index e757ac59..731279b1 100644 --- a/src/MCM.UI/Utils/UISettingsUtils.cs +++ b/src/MCM.UI/Utils/UISettingsUtils.cs @@ -99,7 +99,7 @@ public static void OverrideValues(UndoRedoStack urs, ISettingsPropertyDefinition { IEnumerable enumerableObj => enumerableObj, IEnumerable enumerable => enumerable.Cast(), - _ => Enumerable.Empty() + _ => [] }; } } \ No newline at end of file diff --git a/src/Mod Configuration Menu.sln b/src/Mod Configuration Menu.sln index a7dc653d..14ec777f 100644 --- a/src/Mod Configuration Menu.sln +++ b/src/Mod Configuration Menu.sln @@ -33,7 +33,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{ ..\.github\workflows\docfx.yml = ..\.github\workflows\docfx.yml ..\.github\workflows\dotnet-format-daily.yml = ..\.github\workflows\dotnet-format-daily.yml ..\.github\workflows\test-and-publish.yml = ..\.github\workflows\test-and-publish.yml - ..\.github\workflows\verify-unex-data.yml = ..\.github\workflows\verify-unex-data.yml + ..\.github\workflows\refresh-nexusmods-credentials.yml = ..\.github\workflows\refresh-nexusmods-credentials.yml + ..\.github\workflows\verify-nexusmods-credentials.yml = ..\.github\workflows\verify-nexusmods-credentials.yml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{560DE987-D9C8-431C-A197-08C925905C24}" diff --git a/tests/MCM.Tests.Publish/MCM.Tests.Publish.csproj b/tests/MCM.Tests.Publish/MCM.Tests.Publish.csproj index 87183e39..c211bafd 100644 --- a/tests/MCM.Tests.Publish/MCM.Tests.Publish.csproj +++ b/tests/MCM.Tests.Publish/MCM.Tests.Publish.csproj @@ -5,7 +5,7 @@ netstandard2.0 Aragas Bannerlord.MBOptionScreen.Tests - Mod Configuration Menu v4 Tests + Mod Configuration Menu v5 Tests ^(?!MCM.Tests.Publish).*\.dll|.*\.config Stable_Debug;Beta_Debug;Stable_Release;Beta_Release true diff --git a/tests/MCMv5.Tests/SubModule.cs b/tests/MCMv5.Tests/SubModule.cs index a56d9032..98bb5a20 100644 --- a/tests/MCMv5.Tests/SubModule.cs +++ b/tests/MCMv5.Tests/SubModule.cs @@ -1,4 +1,6 @@ -using MCM.Abstractions.FluentBuilder; +using HarmonyLib.BUTR.Extensions; + +using MCM.Abstractions.FluentBuilder; using MCM.Common; using System; @@ -10,6 +12,16 @@ namespace MCMv5.Tests { public sealed class SubModule : MBSubModuleBase { + private class DropdownContainer + { + public Dropdown Dropdown { get; set; } = new Dropdown(new[] + { + "One", + "Two", + "Three", + }, 2); + } + private bool _boolValue; private int _intValue; private float _floatValue; @@ -25,6 +37,39 @@ public sealed class SubModule : MBSubModuleBase /// protected override void OnBeforeInitialModuleScreenSetAsRoot() { + var storageDropdownValue = new Dropdown(new[] + { + "One", + "Two", + "Three", + }, 2); + var storageDropdown = new StorageRef>(storageDropdownValue); + + var propertyDropdownValue = new DropdownContainer(); + var propertyDropdown = new PropertyRef(SymbolExtensions2.GetPropertyInfo((DropdownContainer x) => x.Dropdown)!, propertyDropdownValue); + + var proxyDropdownValue = new Dropdown(new[] + { + "One", + "Two", + "Three", + }, 2); + var proxyDropdown = new ProxyRef>(() => proxyDropdownValue, o => proxyDropdownValue = o); + + var changingString = new StorageRef(string.Empty); + storageDropdownValue.PropertyChanged += (sender, args) => + { + if (args.PropertyName == "SelectedIndex") + { + if (sender is Dropdown { SelectedIndex: 0 }) + changingString.Value = "Selected Zero"; + if (sender is Dropdown { SelectedIndex: 1 }) + changingString.Value = "Selected One"; + if (sender is Dropdown { SelectedIndex: 2 }) + changingString.Value = "Selected Two "; + } + }; + var builder = BaseSettingsBuilder.Create("Testing_Global_v5", "MCMv5 Testing Fluent Settings")! .SetFormat("xml") .SetFolderName(string.Empty) @@ -42,7 +87,18 @@ protected override void OnBeforeInitialModuleScreenSetAsRoot() .CreateGroup("Testing 3", groupBuilder => groupBuilder .AddText("prop_4", "Test", new ProxyRef(() => _stringValue, o => _stringValue = o), null)) .CreateGroup("Testing 4", groupBuilder => groupBuilder - .AddButton("prop_5", "Test2", new StorageRef((Action) (() => { })), "Test", null)) + .AddButton("prop_5", "Test", new StorageRef((Action) (() => { })), "Test", null)) + .CreateGroup("Testing 5", groupBuilder => groupBuilder + .AddDropdown("prop_6", "Test Storage Ref", storageDropdownValue.SelectedIndex, storageDropdown, null) + .AddButton("prop_6_b", "Reset Storage Ref", new StorageRef((Action) (() => storageDropdownValue.SelectedIndex = 0)), "Reset Storage Ref", null) + + .AddDropdown("prop_7", "Test Property Ref", propertyDropdownValue.Dropdown.SelectedIndex, propertyDropdown, null) + .AddButton("prop_7_b", "Reset Property Ref", new StorageRef((Action) (() => propertyDropdownValue.Dropdown.SelectedIndex = 0)), "Reset Property Ref", null) + + .AddDropdown("prop_8", "Test Proxy Ref", proxyDropdownValue.SelectedIndex, proxyDropdown, null) + .AddButton("prop_8_b", "Reset Proxy Ref", new StorageRef((Action) (() => proxyDropdownValue.SelectedIndex = 0)), "Reset Proxy Ref", null) + .AddText("prop_9", "Test", changingString, null) + ) .CreatePreset("test_v1", "Test", presetBuilder => presetBuilder .SetPropertyValue("prop_1", true) .SetPropertyValue("prop_2", 2) diff --git a/tests/MCMv5.Tests/TestSettingsOrder.cs b/tests/MCMv5.Tests/TestSettingsOrder.cs index 468d4f88..daca9d86 100644 --- a/tests/MCMv5.Tests/TestSettingsOrder.cs +++ b/tests/MCMv5.Tests/TestSettingsOrder.cs @@ -77,5 +77,41 @@ internal sealed class TestSettingsOrder : BaseTestGlobalSettings