Generalize settings annotations

This commit is contained in:
2025-03-02 18:33:01 -06:00
parent 45653067ce
commit f44a7aec2e
5 changed files with 92 additions and 125 deletions

View File

@@ -4,45 +4,49 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
public class SeedSettings { public class SeedSettings {
public const string Omit = "<null>";
public const string NoArg = "<noarg>";
public Mode Mode { get; set; } = Mode.Open; public Mode Mode { get; set; } = Mode.Open;
[SettingName("swords")]
public Weapons Weapons { get; set; } = Weapons.Random; public Weapons Weapons { get; set; } = Weapons.Random;
public Goal Goal { get; set; } = Goal.Ganon; public Goal Goal { get; set; } = Goal.Ganon;
[CommonValue("crystals_ganon")] [SettingName("crystals_ganon")]
public EntryRequirement CrystalsGanon { get; set; } = EntryRequirement.Crystals7; public EntryRequirement CrystalsGanon { get; set; } = EntryRequirement.Crystals7;
[CommonValue("crystals_gt")] [SettingName("crystals_gt")]
[JsonPropertyName("crystals_gt")] [JsonPropertyName("crystals_gt")]
public EntryRequirement CrystalsGT { get; set; } = EntryRequirement.Crystals7; public EntryRequirement CrystalsGT { get; set; } = EntryRequirement.Crystals7;
[SettingName("shuffle")]
public EntranceShuffle EntranceShuffle { get; set; } = EntranceShuffle.Vanilla; public EntranceShuffle EntranceShuffle { get; set; } = EntranceShuffle.Vanilla;
[SettingName("skullwoods")]
public SkullWoodsShuffle SkullWoods { get; set; } = SkullWoodsShuffle.Original; public SkullWoodsShuffle SkullWoods { get; set; } = SkullWoodsShuffle.Original;
[SettingName("linked_drops")]
public LinkedDrops LinkedDrops { get; set; } = LinkedDrops.Unset; public LinkedDrops LinkedDrops { get; set; } = LinkedDrops.Unset;
[SettingName("shufflebosses")]
public BossShuffle BossShuffle { get; set; } = BossShuffle.Vanilla; public BossShuffle BossShuffle { get; set; } = BossShuffle.Vanilla;
[SettingName("shuffleenemies")]
public EnemyShuffle EnemyShuffle { get; set; } = EnemyShuffle.Vanilla; public EnemyShuffle EnemyShuffle { get; set; } = EnemyShuffle.Vanilla;
[CommonValue("keyshuffle")] [SettingName("keyshuffle")]
public DungeonItemLocations SmallKeys { get; set; } = DungeonItemLocations.Dungeon; public DungeonItemLocations SmallKeys { get; set; } = DungeonItemLocations.Dungeon;
[CommonValue("bigkeyshuffle")] [SettingName("bigkeyshuffle")]
[DeniedValues(DungeonItemLocations.Universal)] [DeniedValues(DungeonItemLocations.Universal)]
public DungeonItemLocations BigKeys { get; set; } = DungeonItemLocations.Dungeon; public DungeonItemLocations BigKeys { get; set; } = DungeonItemLocations.Dungeon;
[CommonValue("mapshuffle")] [SettingName("mapshuffle")]
[DeniedValues(DungeonItemLocations.Universal)] [DeniedValues(DungeonItemLocations.Universal)]
public DungeonItemLocations Maps { get; set; } = DungeonItemLocations.Dungeon; public DungeonItemLocations Maps { get; set; } = DungeonItemLocations.Dungeon;
[CommonValue("compassshuffle")] [SettingName("compassshuffle")]
[DeniedValues(DungeonItemLocations.Universal)] [DeniedValues(DungeonItemLocations.Universal)]
public DungeonItemLocations Compasses { get; set; } = DungeonItemLocations.Dungeon; public DungeonItemLocations Compasses { get; set; } = DungeonItemLocations.Dungeon;
[NoSettingName]
public ShopShuffle ShopShuffle { get; set; } = ShopShuffle.Vanilla; public ShopShuffle ShopShuffle { get; set; } = ShopShuffle.Vanilla;
public DropShuffle DropShuffle { get; set; } = DropShuffle.Vanilla; public DropShuffle DropShuffle { get; set; } = DropShuffle.Vanilla;
public Pottery Pottery { get; set; } = Pottery.Vanilla; public Pottery Pottery { get; set; } = Pottery.Vanilla;
@@ -56,7 +60,6 @@
Inverted, Inverted,
} }
[CommonValue("swords")]
public enum Weapons { public enum Weapons {
Random, Random,
Assured, Assured,
@@ -66,36 +69,34 @@
public enum Goal { public enum Goal {
Ganon, Ganon,
[CommonValue("crystals")] FastGanon, [SettingName("crystals")] FastGanon,
[CommonValue("dungeons")] AllDungeons, [SettingName("dungeons")] AllDungeons,
Pedestal, Pedestal,
[CommonValue("triforcehunt")]TriforceHunt, [SettingName("triforcehunt")]TriforceHunt,
GanonHunt, GanonHunt,
Completionist, Completionist,
} }
public enum EntryRequirement { public enum EntryRequirement {
[JsonStringEnumMemberName("0")] [CommonValue("0")] Crystals0 = 0, [JsonStringEnumMemberName("0")] [SettingName("0")] Crystals0 = 0,
[JsonStringEnumMemberName("1")] [CommonValue("1")] Crystals1 = 1, [JsonStringEnumMemberName("1")] [SettingName("1")] Crystals1 = 1,
[JsonStringEnumMemberName("2")] [CommonValue("2")] Crystals2 = 2, [JsonStringEnumMemberName("2")] [SettingName("2")] Crystals2 = 2,
[JsonStringEnumMemberName("3")] [CommonValue("3")] Crystals3 = 3, [JsonStringEnumMemberName("3")] [SettingName("3")] Crystals3 = 3,
[JsonStringEnumMemberName("4")] [CommonValue("4")] Crystals4 = 4, [JsonStringEnumMemberName("4")] [SettingName("4")] Crystals4 = 4,
[JsonStringEnumMemberName("5")] [CommonValue("5")] Crystals5 = 5, [JsonStringEnumMemberName("5")] [SettingName("5")] Crystals5 = 5,
[JsonStringEnumMemberName("6")] [CommonValue("6")] Crystals6 = 6, [JsonStringEnumMemberName("6")] [SettingName("6")] Crystals6 = 6,
[JsonStringEnumMemberName("7")] [CommonValue("7")] Crystals7 = 7, [JsonStringEnumMemberName("7")] [SettingName("7")] Crystals7 = 7,
Random, Random,
} }
[CommonValue("shuffle")]
public enum EntranceShuffle { public enum EntranceShuffle {
Vanilla, Vanilla,
Full, Full,
Crossed, Crossed,
Swapped, Swapped,
[CommonValue("insanity")] Decoupled, [SettingName("insanity")] Decoupled,
} }
[CommonValue("skullwoods")]
public enum SkullWoodsShuffle { public enum SkullWoodsShuffle {
Original, Original,
Restricted, Restricted,
@@ -103,62 +104,58 @@
FollowLinked, FollowLinked,
} }
[CommonValue("linked_drops")]
public enum LinkedDrops { public enum LinkedDrops {
Unset, Unset,
Linked, Linked,
Independent, Independent,
} }
[CommonValue("shufflebosses")]
public enum BossShuffle { public enum BossShuffle {
[CommonValue("none")] Vanilla, [SettingName("none")] Vanilla,
Simple, Simple,
Full, Full,
Random, Random,
[CommonValue("unique")] PrizeUnique, [SettingName("unique")] PrizeUnique,
} }
[CommonValue("shuffleenemies")]
public enum EnemyShuffle { public enum EnemyShuffle {
[CommonValue("none")] Vanilla, [SettingName("none")] Vanilla,
Shuffled, Shuffled,
Mimics, Mimics,
} }
public enum DungeonItemLocations { public enum DungeonItemLocations {
[CommonValue("none")] Dungeon, [SettingName("none")] Dungeon,
Wild, Wild,
Nearby, Nearby,
Universal, Universal,
} }
[CommonValue("shopsanity")]
public enum ShopShuffle { public enum ShopShuffle {
[CommonValue(SeedSettings.Omit)] Vanilla, Vanilla,
[CommonValue(SeedSettings.NoArg)] Shuffled, [AdditionalSetting("--shopsanity")] Shuffled,
} }
public enum DropShuffle { public enum DropShuffle {
[CommonValue("none")] Vanilla, [SettingName("none")] Vanilla,
Keys, Keys,
Underworld, Underworld,
} }
public enum Pottery { public enum Pottery {
[CommonValue("none")] Vanilla, [SettingName("none")] Vanilla,
Keys, [AdditionalSetting("--colorizepots")] Keys,
Cave, [AdditionalSetting("--colorizepots")] Cave,
CaveKeys, [AdditionalSetting("--colorizepots")] CaveKeys,
Reduced, [AdditionalSetting("--colorizepots")] Reduced,
Clustered, [AdditionalSetting("--colorizepots")] Clustered,
NonEmpty, [AdditionalSetting("--colorizepots")] NonEmpty,
Dungeon, [AdditionalSetting("--colorizepots")] Dungeon,
Lottery, Lottery,
} }
public enum PrizeShuffle { public enum PrizeShuffle {
[CommonValue("none")] Vanilla, [SettingName("none")] Vanilla,
Dungeon, Dungeon,
Nearby, Nearby,
Wild, Wild,

View File

@@ -55,34 +55,11 @@
args.Add("--reduce_flashing"); args.Add("--reduce_flashing");
args.Add("--quickswap"); 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));
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("--shufflelinks");
args.Add("--shuffletavern"); 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)); foreach (var arg in this.SettingsProcessor.GetSettings(settings)) {
this.AddArgs(args, this.SettingsProcessor.GetSettingPair(settings.EnemyShuffle)); args.Add(arg);
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");
} }
this.Logger.LogInformation("Randomizing with args: {args}", string.Join(" ", args)); this.Logger.LogInformation("Randomizing with args: {args}", string.Join(" ", args));
@@ -107,16 +84,6 @@
}; };
} }
private void AddArgs(ICollection<string> args, KeyValuePair<string, string> 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) { private async Task GenerationSucceeded(string id, SeedSettings settings) {
var rom = Path.Join(Path.GetTempPath(), string.Format("OR_{0}.sfc", id)); var rom = Path.Join(Path.GetTempPath(), string.Format("OR_{0}.sfc", id));

View File

@@ -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; }
}
}

View File

@@ -1,45 +1,38 @@
namespace ALttPRandomizer.Settings { using System;
namespace ALttPRandomizer.Settings {
using ALttPRandomizer.Model; using ALttPRandomizer.Model;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
public class CommonSettingsProcessor { public class CommonSettingsProcessor {
public KeyValuePair<string, string> GetSettingPair<T>(T value) where T : Enum { public IList<string> GetSettings(SeedSettings settings) {
var name = this.GetValueName(value); var args = new List<string>();
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<CommonValueAttribute>()?.Name; if (prop.GetCustomAttribute<NoSettingNameAttribute>() == null) {
if (settingName == null) { var settingName = prop.GetCustomAttribute<SettingNameAttribute>()?.Name ?? prop.Name.ToLower();
settingName = type.Name.ToLower(); var valueName = fi.GetCustomAttribute<SettingNameAttribute>()?.Name ?? valueFieldName.ToLower();
args.Add(string.Format("--{0}={1}", settingName, valueName));
} }
return new(settingName, name); foreach (var att in fi.GetCustomAttributes<AdditionalSettingAttribute>()) {
} args.Add(att.Setting);
public KeyValuePair<string, string> GetSettingPair<T>(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<CommonValueAttribute>()?.Name ?? fieldName.ToLower();
return new(settingName, name);
}
private string GetValueName<T>(T value) where T : Enum {
Type type = typeof(T);
var fi = type.GetField(value.ToString(), BindingFlags.Static | BindingFlags.Public);
var name = fi?.GetCustomAttribute<CommonValueAttribute>()?.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)) { }
} }
} }

View File

@@ -1,11 +0,0 @@
namespace ALttPRandomizer.Settings {
using System;
internal class CommonValueAttribute : Attribute {
public CommonValueAttribute(string name) {
Name = name;
}
public string Name { get; }
}
}