From f44a7aec2e9cd1ec87a862c4325f8482c90c99ea Mon Sep 17 00:00:00 2001 From: Kara Alexandra Date: Sun, 2 Mar 2025 18:33:01 -0600 Subject: [PATCH] Generalize settings annotations --- ALttPRandomizer/Model/SeedSettings.cs | 85 +++++++++---------- ALttPRandomizer/Randomizer.cs | 41 +-------- ALttPRandomizer/Settings/Attributes.cs | 21 +++++ .../Settings/CommonSettingsProcessor.cs | 59 ++++++------- .../Settings/CommonValueAttribute.cs | 11 --- 5 files changed, 92 insertions(+), 125 deletions(-) create mode 100644 ALttPRandomizer/Settings/Attributes.cs delete mode 100644 ALttPRandomizer/Settings/CommonValueAttribute.cs diff --git a/ALttPRandomizer/Model/SeedSettings.cs b/ALttPRandomizer/Model/SeedSettings.cs index 954bba4..5be1165 100644 --- a/ALttPRandomizer/Model/SeedSettings.cs +++ b/ALttPRandomizer/Model/SeedSettings.cs @@ -4,45 +4,49 @@ using System.Text.Json.Serialization; public class SeedSettings { - public const string Omit = ""; - public const string NoArg = ""; - public Mode Mode { get; set; } = Mode.Open; + [SettingName("swords")] public Weapons Weapons { get; set; } = Weapons.Random; public Goal Goal { get; set; } = Goal.Ganon; - [CommonValue("crystals_ganon")] + [SettingName("crystals_ganon")] public EntryRequirement CrystalsGanon { get; set; } = EntryRequirement.Crystals7; - [CommonValue("crystals_gt")] + [SettingName("crystals_gt")] [JsonPropertyName("crystals_gt")] public EntryRequirement CrystalsGT { get; set; } = EntryRequirement.Crystals7; + [SettingName("shuffle")] public EntranceShuffle EntranceShuffle { get; set; } = EntranceShuffle.Vanilla; + [SettingName("skullwoods")] public SkullWoodsShuffle SkullWoods { get; set; } = SkullWoodsShuffle.Original; + [SettingName("linked_drops")] public LinkedDrops LinkedDrops { get; set; } = LinkedDrops.Unset; + [SettingName("shufflebosses")] public BossShuffle BossShuffle { get; set; } = BossShuffle.Vanilla; + [SettingName("shuffleenemies")] public EnemyShuffle EnemyShuffle { get; set; } = EnemyShuffle.Vanilla; - [CommonValue("keyshuffle")] + [SettingName("keyshuffle")] public DungeonItemLocations SmallKeys { get; set; } = DungeonItemLocations.Dungeon; - [CommonValue("bigkeyshuffle")] + [SettingName("bigkeyshuffle")] [DeniedValues(DungeonItemLocations.Universal)] public DungeonItemLocations BigKeys { get; set; } = DungeonItemLocations.Dungeon; - [CommonValue("mapshuffle")] + [SettingName("mapshuffle")] [DeniedValues(DungeonItemLocations.Universal)] public DungeonItemLocations Maps { get; set; } = DungeonItemLocations.Dungeon; - [CommonValue("compassshuffle")] + [SettingName("compassshuffle")] [DeniedValues(DungeonItemLocations.Universal)] public DungeonItemLocations Compasses { get; set; } = DungeonItemLocations.Dungeon; + [NoSettingName] public ShopShuffle ShopShuffle { get; set; } = ShopShuffle.Vanilla; public DropShuffle DropShuffle { get; set; } = DropShuffle.Vanilla; public Pottery Pottery { get; set; } = Pottery.Vanilla; @@ -56,7 +60,6 @@ Inverted, } - [CommonValue("swords")] public enum Weapons { Random, Assured, @@ -66,36 +69,34 @@ public enum Goal { Ganon, - [CommonValue("crystals")] FastGanon, - [CommonValue("dungeons")] AllDungeons, + [SettingName("crystals")] FastGanon, + [SettingName("dungeons")] AllDungeons, Pedestal, - [CommonValue("triforcehunt")]TriforceHunt, + [SettingName("triforcehunt")]TriforceHunt, GanonHunt, Completionist, } public enum EntryRequirement { - [JsonStringEnumMemberName("0")] [CommonValue("0")] Crystals0 = 0, - [JsonStringEnumMemberName("1")] [CommonValue("1")] Crystals1 = 1, - [JsonStringEnumMemberName("2")] [CommonValue("2")] Crystals2 = 2, - [JsonStringEnumMemberName("3")] [CommonValue("3")] Crystals3 = 3, - [JsonStringEnumMemberName("4")] [CommonValue("4")] Crystals4 = 4, - [JsonStringEnumMemberName("5")] [CommonValue("5")] Crystals5 = 5, - [JsonStringEnumMemberName("6")] [CommonValue("6")] Crystals6 = 6, - [JsonStringEnumMemberName("7")] [CommonValue("7")] Crystals7 = 7, + [JsonStringEnumMemberName("0")] [SettingName("0")] Crystals0 = 0, + [JsonStringEnumMemberName("1")] [SettingName("1")] Crystals1 = 1, + [JsonStringEnumMemberName("2")] [SettingName("2")] Crystals2 = 2, + [JsonStringEnumMemberName("3")] [SettingName("3")] Crystals3 = 3, + [JsonStringEnumMemberName("4")] [SettingName("4")] Crystals4 = 4, + [JsonStringEnumMemberName("5")] [SettingName("5")] Crystals5 = 5, + [JsonStringEnumMemberName("6")] [SettingName("6")] Crystals6 = 6, + [JsonStringEnumMemberName("7")] [SettingName("7")] Crystals7 = 7, Random, } - [CommonValue("shuffle")] public enum EntranceShuffle { Vanilla, Full, Crossed, Swapped, - [CommonValue("insanity")] Decoupled, + [SettingName("insanity")] Decoupled, } - [CommonValue("skullwoods")] public enum SkullWoodsShuffle { Original, Restricted, @@ -103,62 +104,58 @@ FollowLinked, } - [CommonValue("linked_drops")] public enum LinkedDrops { Unset, Linked, Independent, } - [CommonValue("shufflebosses")] public enum BossShuffle { - [CommonValue("none")] Vanilla, + [SettingName("none")] Vanilla, Simple, Full, Random, - [CommonValue("unique")] PrizeUnique, + [SettingName("unique")] PrizeUnique, } - [CommonValue("shuffleenemies")] public enum EnemyShuffle { - [CommonValue("none")] Vanilla, + [SettingName("none")] Vanilla, Shuffled, Mimics, } public enum DungeonItemLocations { - [CommonValue("none")] Dungeon, + [SettingName("none")] Dungeon, Wild, Nearby, Universal, } - [CommonValue("shopsanity")] public enum ShopShuffle { - [CommonValue(SeedSettings.Omit)] Vanilla, - [CommonValue(SeedSettings.NoArg)] Shuffled, + Vanilla, + [AdditionalSetting("--shopsanity")] Shuffled, } public enum DropShuffle { - [CommonValue("none")] Vanilla, + [SettingName("none")] Vanilla, Keys, Underworld, } public enum Pottery { - [CommonValue("none")] Vanilla, - Keys, - Cave, - CaveKeys, - Reduced, - Clustered, - NonEmpty, - Dungeon, + [SettingName("none")] Vanilla, + [AdditionalSetting("--colorizepots")] Keys, + [AdditionalSetting("--colorizepots")] Cave, + [AdditionalSetting("--colorizepots")] CaveKeys, + [AdditionalSetting("--colorizepots")] Reduced, + [AdditionalSetting("--colorizepots")] Clustered, + [AdditionalSetting("--colorizepots")] NonEmpty, + [AdditionalSetting("--colorizepots")] Dungeon, Lottery, } public enum PrizeShuffle { - [CommonValue("none")] Vanilla, + [SettingName("none")] Vanilla, Dungeon, Nearby, Wild, diff --git a/ALttPRandomizer/Randomizer.cs b/ALttPRandomizer/Randomizer.cs index e45a139..1547f9a 100644 --- a/ALttPRandomizer/Randomizer.cs +++ b/ALttPRandomizer/Randomizer.cs @@ -55,34 +55,11 @@ args.Add("--reduce_flashing"); args.Add("--quickswap"); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.Mode)); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.Weapons)); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.Goal)); + args.Add("--shufflelinks"); + args.Add("--shuffletavern"); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(nameof(SeedSettings.CrystalsGanon), settings.CrystalsGanon)); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(nameof(SeedSettings.CrystalsGT), settings.CrystalsGT)); - - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(nameof(SeedSettings.SmallKeys), settings.SmallKeys)); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(nameof(SeedSettings.BigKeys), settings.BigKeys)); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(nameof(SeedSettings.Maps), settings.Maps)); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(nameof(SeedSettings.Compasses), settings.Compasses)); - - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.EntranceShuffle)); - if (settings.EntranceShuffle != EntranceShuffle.Vanilla) { - args.Add("--shufflelinks"); - args.Add("--shuffletavern"); - } - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.SkullWoods)); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.LinkedDrops)); - - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.BossShuffle)); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.EnemyShuffle)); - - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.ShopShuffle)); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.DropShuffle)); - this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.Pottery)); - if (settings.Pottery != Pottery.Vanilla && settings.Pottery != Pottery.Lottery) { - args.Add("--colorizepots"); + foreach (var arg in this.SettingsProcessor.GetSettings(settings)) { + args.Add(arg); } this.Logger.LogInformation("Randomizing with args: {args}", string.Join(" ", args)); @@ -107,16 +84,6 @@ }; } - private void AddArgs(ICollection args, KeyValuePair setting) { - if (setting.Value != null) { - if (setting.Value == SeedSettings.NoArg) { - args.Add(string.Format("--{0}", setting.Key)); - } else if (setting.Value != SeedSettings.Omit) { - args.Add(string.Format("--{0}={1}", setting.Key, setting.Value)); - } - } - } - private async Task GenerationSucceeded(string id, SeedSettings settings) { var rom = Path.Join(Path.GetTempPath(), string.Format("OR_{0}.sfc", id)); diff --git a/ALttPRandomizer/Settings/Attributes.cs b/ALttPRandomizer/Settings/Attributes.cs new file mode 100644 index 0000000..6da3fb8 --- /dev/null +++ b/ALttPRandomizer/Settings/Attributes.cs @@ -0,0 +1,21 @@ +namespace ALttPRandomizer.Settings { + using System; + + internal class SettingNameAttribute : Attribute { + public SettingNameAttribute(string name) { + this.Name = name; + } + + public string Name { get; } + } + + internal class NoSettingNameAttribute : Attribute { } + + internal class AdditionalSettingAttribute : Attribute { + public AdditionalSettingAttribute(string setting) { + this.Setting = setting; + } + + public string Setting { get; } + } +} diff --git a/ALttPRandomizer/Settings/CommonSettingsProcessor.cs b/ALttPRandomizer/Settings/CommonSettingsProcessor.cs index ee031be..b948420 100644 --- a/ALttPRandomizer/Settings/CommonSettingsProcessor.cs +++ b/ALttPRandomizer/Settings/CommonSettingsProcessor.cs @@ -1,45 +1,38 @@ -namespace ALttPRandomizer.Settings { +using System; + +namespace ALttPRandomizer.Settings { using ALttPRandomizer.Model; - using System; using System.Collections.Generic; using System.Reflection; public class CommonSettingsProcessor { - public KeyValuePair GetSettingPair(T value) where T : Enum { - var name = this.GetValueName(value); + public IList GetSettings(SeedSettings settings) { + var args = new List(); - Type type = typeof(T); + var props = typeof(SeedSettings).GetProperties(BindingFlags.Instance | BindingFlags.Public); + foreach (var prop in props) { + var value = prop.GetValue(settings) ?? throw new SettingsLookupException("settings.{} not found", prop.Name); + var valueFieldName = value.ToString() ?? throw new SettingsLookupException("settings.{}.ToString() returned null", prop.Name); + var fi = prop.PropertyType.GetField(valueFieldName, BindingFlags.Static | BindingFlags.Public) + ?? throw new SettingsLookupException("Could not get field info for value {}.{}", prop.PropertyType, valueFieldName); - var settingName = type.GetCustomAttribute()?.Name; - if (settingName == null) { - settingName = type.Name.ToLower(); + if (prop.GetCustomAttribute() == null) { + var settingName = prop.GetCustomAttribute()?.Name ?? prop.Name.ToLower(); + var valueName = fi.GetCustomAttribute()?.Name ?? valueFieldName.ToLower(); + + args.Add(string.Format("--{0}={1}", settingName, valueName)); + } + + foreach (var att in fi.GetCustomAttributes()) { + args.Add(att.Setting); + } } - return new(settingName, name); - } - - public KeyValuePair GetSettingPair(string fieldName, T value) where T : Enum { - var name = this.GetValueName(value); - - var fi = typeof(SeedSettings).GetProperty(fieldName, BindingFlags.Instance | BindingFlags.Public); - - var settingName = fi?.GetCustomAttribute()?.Name ?? fieldName.ToLower(); - - return new(settingName, name); - } - - private string GetValueName(T value) where T : Enum { - Type type = typeof(T); - - var fi = type.GetField(value.ToString(), BindingFlags.Static | BindingFlags.Public); - - var name = fi?.GetCustomAttribute()?.Name; - - if (name != null) { - return name; - } else { - return value.ToString().ToLower(); - } + return args; } } + + public class SettingsLookupException : Exception { + public SettingsLookupException(string message, params object?[] args) : base(string.Format(message, args)) { } + } } diff --git a/ALttPRandomizer/Settings/CommonValueAttribute.cs b/ALttPRandomizer/Settings/CommonValueAttribute.cs deleted file mode 100644 index 253db90..0000000 --- a/ALttPRandomizer/Settings/CommonValueAttribute.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace ALttPRandomizer.Settings { - using System; - - internal class CommonValueAttribute : Attribute { - public CommonValueAttribute(string name) { - Name = name; - } - - public string Name { get; } - } -}