diff --git a/.dockerignore b/.dockerignore index 3ec5ed9..c82f26f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,5 @@ -scripts/ +Dockerfile +justfile ALttPRandomizer/appsettings.json ALttPRandomizer/appsettings.Development.json @@ -10,4 +11,10 @@ ALttPRandomizer/[Bb]in */DR_* */ER_* */OR_* -*/data/base2current.json +*/GK_* +*.sfc +*_Spoiler.txt + +!alttp.sfc + +# */data/base2current.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.gitmodules b/.gitmodules index 67db478..45e4398 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,12 @@ -[submodule "ALttPDoorRandomizer"] - path = ALttPDoorRandomizer - url = https://github.com/ardnaxelarak/ALttPDoorRandomizer [submodule "BaseRandomizer"] path = BaseRandomizer - url = https://github.com/ardnaxelarak/ALttPDoorRandomizer + url = https://git.gwaa.kiwi/alttpr-gwaa-kiwi/alttpr-python + branch = GwaaKiwi [submodule "Apr2025Randomizer"] path = Apr2025Randomizer - url = https://github.com/ardnaxelarak/ALttPDoorRandomizer -[submodule "DungeonMapRandomizer"] - path = DungeonMapRandomizer - url = git@github.com:ardnaxelarak/ALttPDoorRandomizer + url = https://git.gwaa.kiwi/alttpr-gwaa-kiwi/alttpr-python + branch = apr_2025 +[submodule "BetaRandomizer"] + path = BetaRandomizer + url = https://git.gwaa.kiwi/alttpr-gwaa-kiwi/alttpr-python + branch = DungeonMap diff --git a/ALttPRandomizer/JsonOptions.cs b/ALttPRandomizer/JsonOptions.cs index 3af48e8..d7dc7c4 100644 --- a/ALttPRandomizer/JsonOptions.cs +++ b/ALttPRandomizer/JsonOptions.cs @@ -3,7 +3,7 @@ using System.Text.Json.Serialization; public static class JsonOptions { - public static JsonSerializerOptions Default = new JsonSerializerOptions(JsonSerializerDefaults.Web) { + public static readonly JsonSerializerOptions Default = new JsonSerializerOptions(JsonSerializerDefaults.Web) { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, NumberHandling = JsonNumberHandling.Strict, }.WithStringEnum(); diff --git a/ALttPRandomizer/Model/SeedSettings.cs b/ALttPRandomizer/Model/SeedSettings.cs index 2b6e35c..9558bf8 100644 --- a/ALttPRandomizer/Model/SeedSettings.cs +++ b/ALttPRandomizer/Model/SeedSettings.cs @@ -26,20 +26,24 @@ public Goal Goal { get; set; } = Goal.Ganon; [SettingName("crystals_ganon")] + [IgnoreSetting(Apr2025)] public EntryRequirement CrystalsGanon { get; set; } = EntryRequirement.Crystals7; [SettingName("bosses_ganon")] - [NoSettingName([Apr2025, Base])] + [IgnoreSetting(Apr2025, Base)] public BossRequirement BossesGanon { get; set; } = BossRequirement.Bosses8of10; + [NoSettingName] + [IgnoreSetting(Apr2025)] + public TriforceRequirement TriforcePieces { get; set; } = TriforceRequirement.Triforce20of30; + [SettingName("crystals_gt")] [JsonPropertyName("crystals_gt")] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public EntryRequirement CrystalsGT { get; set; } = EntryRequirement.Crystals7; [SettingName("ganon_item")] - [RequiredSetting([Apr2025], GanonItem.Silver)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public GanonItem GanonItem { get; set; } = GanonItem.Silver; [SettingName("shuffle")] @@ -47,32 +51,27 @@ public EntranceShuffle EntranceShuffle { get; set; } = EntranceShuffle.Vanilla; [NoSettingName] - [RequiredSetting([Apr2025], LinksHouse.Vanilla)] + [IgnoreSetting(Apr2025)] public LinksHouse LinksHouse { get; set; } = LinksHouse.Vanilla; [SettingName("skullwoods")] - [RequiredSetting([Apr2025], SkullWoodsShuffle.Original)] - [NoSettingName([Apr2025])] - public SkullWoodsShuffle SkullWoods { get; set; } = SkullWoodsShuffle.Original; + [IgnoreSetting(Apr2025)] + public SkullWoodsShuffle SkullWoods { get; set; } = SkullWoodsShuffle.Default; [SettingName("linked_drops")] - [RequiredSetting([Apr2025], LinkedDrops.Unset)] - [NoSettingName([Apr2025])] - public LinkedDrops LinkedDrops { get; set; } = LinkedDrops.Unset; + [IgnoreSetting(Apr2025)] + public LinkedDrops LinkedDrops { get; set; } = LinkedDrops.Default; [SettingName("shufflebosses")] - [RequiredSetting([Apr2025], BossShuffle.Vanilla)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public BossShuffle BossShuffle { get; set; } = BossShuffle.Vanilla; [SettingName("shuffleenemies")] - [RequiredSetting([Apr2025], EnemyShuffle.Vanilla)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public EnemyShuffle EnemyShuffle { get; set; } = EnemyShuffle.Vanilla; [SettingName("shuffle_damage_table")] - [RequiredSetting([Apr2025], DamageTableShuffle.Vanilla)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public DamageTableShuffle DamageTableShuffle { get; set; } = DamageTableShuffle.Vanilla; [SettingName("keyshuffle")] @@ -81,44 +80,37 @@ public KeyLocations SmallKeys { get; set; } = KeyLocations.Dungeon; [SettingName("bigkeyshuffle")] - [RequiredSetting([Apr2025], DungeonItemLocations.Dungeon)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public DungeonItemLocations BigKeys { get; set; } = DungeonItemLocations.Dungeon; [SettingName("mapshuffle")] - [RequiredSetting([Apr2025], DungeonItemLocations.Dungeon)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public DungeonItemLocations Maps { get; set; } = DungeonItemLocations.Dungeon; [SettingName("compassshuffle")] - [RequiredSetting([Apr2025], DungeonItemLocations.Dungeon)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public DungeonItemLocations Compasses { get; set; } = DungeonItemLocations.Dungeon; [SettingName("showloot")] - [RequiredSetting([Apr2025, Base], ShowLoot.Never)] - [NoSettingName([Apr2025, Base])] + [IgnoreSetting(Apr2025, Base)] public ShowLoot ShowLoot { get; set; } = ShowLoot.Never; [SettingName("showmap")] - [RequiredSetting([Apr2025, Base], ShowMap.Map)] - [NoSettingName([Apr2025, Base])] + [IgnoreSetting(Apr2025, Base)] public ShowMap ShowMap { get; set; } = ShowMap.Map; [NoSettingName] - [RequiredSetting([Apr2025], ShopShuffle.Vanilla)] + [IgnoreSetting(Apr2025)] public ShopShuffle ShopShuffle { get; set; } = ShopShuffle.Vanilla; - [RequiredSetting([Apr2025], DropShuffle.Vanilla)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public DropShuffle DropShuffle { get; set; } = DropShuffle.Vanilla; - [RequiredSetting([Apr2025], Pottery.Vanilla)] - [NoSettingName([Apr2025])] - public Pottery Pottery { get; set; } = Pottery.Vanilla; + [SettingName("pottery")] + [IgnoreSetting(Apr2025)] + public PotShuffle PotShuffle { get; set; } = PotShuffle.Vanilla; - [RequiredSetting([Apr2025], PrizeShuffle.Vanilla)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public PrizeShuffle PrizeShuffle { get; set; } = PrizeShuffle.Vanilla; [NoSettingName] @@ -126,57 +118,55 @@ public BootsSettings Boots { get; set; } = BootsSettings.Normal; [NoSettingName] - [RequiredSetting([Apr2025], FluteSettings.Normal)] + [IgnoreSetting(Apr2025)] public FluteSettings Flute { get; set; } = FluteSettings.Normal; [SettingName("dark_rooms")] - [RequiredSetting([Apr2025], DarkRoomSettings.RequireLamp)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public DarkRoomSettings DarkRooms { get; set; } = DarkRoomSettings.RequireLamp; [NoSettingName] - [RequiredSetting([Apr2025], BombSettings.Normal)] + [IgnoreSetting(Apr2025)] public BombSettings Bombs { get; set; } = BombSettings.Normal; [NoSettingName] - [RequiredSetting([Apr2025], BookSettings.Normal)] + [IgnoreSetting(Apr2025)] public BookSettings Book { get; set; } = BookSettings.Normal; [NoSettingName] - [RequiredSetting([Apr2025], MirrorSettings.Normal)] + [IgnoreSetting(Apr2025)] public MirrorSettings Mirror { get; set; } = MirrorSettings.Normal; [SettingName("door_shuffle")] - [RequiredSetting([Apr2025], DoorShuffle.Vanilla)] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public DoorShuffle DoorShuffle { get; set; } = DoorShuffle.Vanilla; [SettingName("intensity")] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public DoorLobbies Lobbies { get; set; } = DoorLobbies.Vanilla; [SettingName("door_type_mode")] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public DoorTypeMode DoorTypeMode { get; set; } = DoorTypeMode.Big; [SettingName("trap_door_mode")] - [NoSettingName([Apr2025])] - public TrapDoorMode TrapDoorMode { get; set; } = TrapDoorMode.Optional; + [IgnoreSetting(Apr2025)] + public TrapDoorMode TrapDoorMode { get; set; } = TrapDoorMode.Some; [NoSettingName] - [RequiredSetting([Apr2025], FollowerShuffle.Vanilla)] + [IgnoreSetting(Apr2025)] public FollowerShuffle FollowerShuffle { get; set; } = FollowerShuffle.Vanilla; [SettingName("ow_fluteshuffle")] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public FluteShuffle FluteShuffle { get; set; } = FluteShuffle.Vanilla; [NoSettingName] - [RequiredSetting([Apr2025], TileSwap.Vanilla)] + [IgnoreSetting(Apr2025)] public TileSwap TileSwap { get; set; } = TileSwap.Vanilla; [SettingName("damage_challenge")] - [NoSettingName([Apr2025])] + [IgnoreSetting(Apr2025)] public DamageChallengeMode DamageChallenge { get; set; } = DamageChallengeMode.Normal; [NoSettingName] @@ -187,7 +177,7 @@ { [RandomizerName(BaseRandomizer.Name)] Base, [RandomizerName(Apr2025Randomizer.Name)] Apr2025, - [RandomizerName(BaseRandomizer.DungeonMapName)] DungeonMap, + [RandomizerName(BaseRandomizer.BetaName)] Beta, } public enum RaceMode { @@ -234,6 +224,14 @@ Random, } + public enum TriforceRequirement { + [JsonStringEnumMemberName("8of10")] [AdditionalSetting("--triforce_goal=8", "--triforce_pool=10")] Triforce8of10, + [JsonStringEnumMemberName("20of30")] [AdditionalSetting("--triforce_goal=20", "--triforce_pool=30")] Triforce20of30, + [JsonStringEnumMemberName("67of100")] [AdditionalSetting("--triforce_goal=67", "--triforce_pool=100")] Triforce67of100, + [JsonStringEnumMemberName("125of175")] [AdditionalSetting("--triforce_goal=125", "--triforce_pool=175")] Triforce125of175, + [JsonStringEnumMemberName("400of500")] [AdditionalSetting("--triforce_goal=400", "--triforce_pool=500")] Triforce400of500, + } + public enum BossRequirement { [JsonStringEnumMemberName("0of10")] [SettingName("0")] Bosses0of10, [JsonStringEnumMemberName("1of10")] [SettingName("1")] Bosses1of10, @@ -294,14 +292,14 @@ } public enum SkullWoodsShuffle { - Original, - Restricted, + [SettingName("original")] Default, + [SettingName("restricted")] VanillaDrops, Loose, - FollowLinked, + [SettingName("follow_linked")] Chaos, } public enum LinkedDrops { - Unset, + [SettingName("unset")] Default, Linked, Independent, } @@ -349,7 +347,7 @@ Underworld, } - public enum Pottery { + public enum PotShuffle { [SettingName("none")] Vanilla, [AdditionalSetting("--colorizepots")] Keys, [AdditionalSetting("--colorizepots")] Cave, @@ -358,7 +356,7 @@ [AdditionalSetting("--colorizepots")] Clustered, [AdditionalSetting("--colorizepots")] NonEmpty, [AdditionalSetting("--colorizepots")] Dungeon, - Lottery, + [SettingName("lottery")] All, } public enum PrizeShuffle { @@ -405,7 +403,7 @@ [SettingName("always_light_cone")] AlwaysLightCone, [SettingName("no_dark_rooms")] NoDarkRooms, [SettingName("require_lamp")] [AddStartingItems("Lamp")] StartingLamp, - [SettingName("always_in_logic")] AlwaysInLogic, + [SettingName("always_in_logic")] DarkInLogic, } public enum BombSettings { @@ -440,7 +438,7 @@ public enum TrapDoorMode { Vanilla, - Optional, + [SettingName("optional")] Some, Boss, [SettingName("oneway")] RemoveAll, } diff --git a/ALttPRandomizer/Options/ServiceOptions.cs b/ALttPRandomizer/Options/ServiceOptions.cs index 2e72ee3..bc3a449 100644 --- a/ALttPRandomizer/Options/ServiceOptions.cs +++ b/ALttPRandomizer/Options/ServiceOptions.cs @@ -4,11 +4,15 @@ public class ServiceOptions { public string Baserom { get; set; } = null!; - public string PythonPath { get; set; } = null!; public string FlipsPath { get; set; } = null!; - public IList AllowedCors { get; set; } = new List(); - public AzureSettings AzureSettings { get; set; } = new AzureSettings(); - public IDictionary RandomizerPaths { get; set; } = new Dictionary(); + public List AllowedCors { get; set; } = []; + public AzureSettings AzureSettings { get; set; } = new(); + public Dictionary Generators { get; set; } = new(); + } + + public class GeneratorSettings { + public string WorkingDirectory { get; set; } = null!; + public List RandomizerCommand { get; set; } = []; } public class AzureSettings { diff --git a/ALttPRandomizer/Program.cs b/ALttPRandomizer/Program.cs index de27c27..d6e05b2 100644 --- a/ALttPRandomizer/Program.cs +++ b/ALttPRandomizer/Program.cs @@ -72,7 +72,7 @@ builder.Services.AddSingleton(); builder.Services.AddKeyedScoped(BaseRandomizer.Name); - builder.Services.AddKeyedScoped(BaseRandomizer.DungeonMapName); + builder.Services.AddKeyedScoped(BaseRandomizer.BetaName); builder.Services.AddKeyedScoped(Apr2025Randomizer.Name); builder.Services.AddScoped(); diff --git a/ALttPRandomizer/Randomizers/Apr2025Randomizer.cs b/ALttPRandomizer/Randomizers/Apr2025Randomizer.cs index 92bc130..30b2196 100644 --- a/ALttPRandomizer/Randomizers/Apr2025Randomizer.cs +++ b/ALttPRandomizer/Randomizers/Apr2025Randomizer.cs @@ -9,6 +9,7 @@ using System; using System.Diagnostics; using System.IO; + using System.Linq; using System.Text.Json; using System.Threading.Tasks; @@ -40,15 +41,14 @@ public async Task Randomize(string id, SeedSettings settings, bool uploadSettings = true) { Logger.LogDebug("Recieved request for id {id} to randomize settings {@settings}", id, settings); - var start = new ProcessStartInfo() { - FileName = Configuration.PythonPath, - WorkingDirectory = Configuration.RandomizerPaths[Name], + var generatorSettings = this.Configuration.Generators[Name]; + var start = new ProcessStartInfo(generatorSettings.RandomizerCommand[0], generatorSettings.RandomizerCommand.Skip(1)) { + WorkingDirectory = generatorSettings.WorkingDirectory, RedirectStandardOutput = true, RedirectStandardError = true, }; var args = start.ArgumentList; - args.Add("EntranceRandomizer.py"); args.Add("--rom"); args.Add(Configuration.Baserom); @@ -58,15 +58,11 @@ args.Add("--outputname"); args.Add(id); - args.Add("--json_spoiler"); - - args.Add("--quickswap"); - foreach (var arg in SettingsProcessor.GetSettings(Instance, settings)) { args.Add(arg); } - Logger.LogInformation("Randomizing with args: {args}", string.Join(" ", args)); + Logger.LogInformation("Randomizing {id} with command: {command} {args}", id, start.FileName, string.Join(" ", args.Select(arg => arg.Contains(" ") ? $"\"{arg}\"" : arg))); var generating = string.Format("{0}/generating", id); await AzureStorage.UploadFile(generating, BinaryData.Empty); diff --git a/ALttPRandomizer/Randomizers/BaseRandomizer.cs b/ALttPRandomizer/Randomizers/BaseRandomizer.cs index aff92b9..10598ae 100644 --- a/ALttPRandomizer/Randomizers/BaseRandomizer.cs +++ b/ALttPRandomizer/Randomizers/BaseRandomizer.cs @@ -16,7 +16,7 @@ public class BaseRandomizer : IRandomizer { public const string Name = "base"; - public const string DungeonMapName = "dungeon_map"; + public const string BetaName = "beta"; public const int MULTI_TRIES = 100; public const int SINGLE_TRIES = 5; @@ -57,7 +57,7 @@ } } - private IList GetArgs(SeedSettings settings) { + private List GetArgs(SeedSettings settings) { var args = new List() { "--reduce_flashing", "--quickswap", @@ -73,26 +73,25 @@ } if (settings.DoorShuffle != DoorShuffle.Vanilla || settings.DropShuffle != DropShuffle.Vanilla - || (settings.Pottery != Pottery.Vanilla && settings.Pottery != Pottery.Cave)) { + || (settings.PotShuffle != PotShuffle.Vanilla && settings.PotShuffle != PotShuffle.Cave)) { args.Add("--dungeon_counters=on"); } return args; } - private async Task StartProcess(string randomizerName, string id, IEnumerable settings, Func completed) { - var start = new ProcessStartInfo() { - FileName = Configuration.PythonPath, - WorkingDirectory = Configuration.RandomizerPaths[randomizerName], + private async Task StartProcess(string generatorName, string id, IEnumerable settings, Func completed) { + var generatorSettings = this.Configuration.Generators[generatorName]; + + var start = new ProcessStartInfo(generatorSettings.RandomizerCommand[0], generatorSettings.RandomizerCommand.Skip(1)) { + WorkingDirectory = generatorSettings.WorkingDirectory, RedirectStandardOutput = true, RedirectStandardError = true, }; var args = start.ArgumentList; - args.Add("DungeonRandomizer.py"); args.Add("--rom"); args.Add(Configuration.Baserom); - args.Add("--bps"); args.Add("--outputpath"); args.Add(Path.GetTempPath()); @@ -100,13 +99,11 @@ args.Add("--outputname"); args.Add(id); - args.Add("--spoiler=json"); - foreach (var arg in settings) { args.Add(arg); } - Logger.LogInformation("Randomizing {id} with args: {args}", id, string.Join(" ", args.Select(arg => $"\"{arg}\""))); + Logger.LogInformation("Randomizing {id} with command: {command} {args}", id, start.FileName, string.Join(" ", args.Select(arg => arg.Contains(" ") ? $"\"{arg}\"" : arg))); var generating = string.Format("{0}/generating", id); await AzureStorage.UploadFile(generating, BinaryData.Empty); @@ -114,8 +111,16 @@ var process = Process.Start(start) ?? throw new GenerationFailedException("Process failed to start."); process.EnableRaisingEvents = true; - process.OutputDataReceived += (_, args) => Logger.LogInformation("Randomizer {id} STDOUT: {output}", id, args.Data); - process.ErrorDataReceived += (_, args) => Logger.LogInformation("Randomizer {id} STDERR: {output}", id, args.Data); + process.OutputDataReceived += (_, args) => { + if (args.Data != null) { + Logger.LogInformation("Randomizer {id} STDOUT: {output}", id, args.Data); + } + }; + process.ErrorDataReceived += (_, args) => { + if (args.Data != null) { + Logger.LogInformation("Randomizer {id} STDERR: {output}", id, args.Data); + } + }; process.BeginOutputReadLine(); process.BeginErrorReadLine(); @@ -270,7 +275,7 @@ Logger.LogInformation("Finished uploading multiworld id {id}", id); } finally { var generating = string.Format("{0}/generating", id); - var deleteGenerating = AzureStorage.DeleteFile(generating); + await AzureStorage.DeleteFile(generating); } } @@ -293,11 +298,9 @@ return JsonSerializer.SerializeToDocument(processed, JsonOptions.Default); } - private async Task GenerationFailed(string id, int exitcode) { + private async Task GenerationFailed(string id, int _) { var generating = string.Format("{0}/generating", id); - var deleteGenerating = AzureStorage.DeleteFile(generating); - - await Task.WhenAll(deleteGenerating); + await AzureStorage.DeleteFile(generating); } } } diff --git a/ALttPRandomizer/Settings/Attributes.cs b/ALttPRandomizer/Settings/Attributes.cs index 0f5b3bb..f258c4b 100644 --- a/ALttPRandomizer/Settings/Attributes.cs +++ b/ALttPRandomizer/Settings/Attributes.cs @@ -42,21 +42,27 @@ internal class NoSettingNameAttribute : RandomizerSpecificAttribute { public NoSettingNameAttribute() : base(null) { } - public NoSettingNameAttribute(RandomizerInstance[] randomizers) : base(randomizers) { } + public NoSettingNameAttribute(params RandomizerInstance[] randomizers) : base(randomizers) { } } + internal class IgnoreSettingAttribute : RandomizerSpecificAttribute { + public IgnoreSettingAttribute(params RandomizerInstance[] randomizers) : base(randomizers) { } + } + + [AttributeUsage(AttributeTargets.Field, AllowMultiple=true)] internal class AdditionalSettingAttribute : RandomizerSpecificAttribute { - public AdditionalSettingAttribute(string setting) : base(null) { - this.Setting = setting; + public AdditionalSettingAttribute(params string[] settings) : base(null) { + this.Settings = settings; } - public AdditionalSettingAttribute(RandomizerInstance[] randomizers, string setting) : base(randomizers) { - this.Setting = setting; + public AdditionalSettingAttribute(RandomizerInstance[] randomizers, params string[] settings) : base(randomizers) { + this.Settings = settings; } - public string Setting { get; } + public string[] Settings { get; } } + [AttributeUsage(AttributeTargets.Field, AllowMultiple=true)] internal class AddStartingItemsAttribute : RandomizerSpecificAttribute { public AddStartingItemsAttribute(params string[] items) : base(null) { this.Items = items; @@ -69,6 +75,7 @@ public string[] Items { get; } } + [AttributeUsage(AttributeTargets.Property, AllowMultiple=true)] internal class RequiredSettingAttribute : RandomizerSpecificAttribute { public RequiredSettingAttribute(params object[] values) : base(null) { this.Values = values; @@ -81,6 +88,7 @@ public object[] Values { get; } } + [AttributeUsage(AttributeTargets.Property, AllowMultiple=true)] internal class ForbiddenSettingAttribute : RandomizerSpecificAttribute { public ForbiddenSettingAttribute(params object[] values) : base(null) { this.Values = values; diff --git a/ALttPRandomizer/Settings/CommonSettingsProcessor.cs b/ALttPRandomizer/Settings/CommonSettingsProcessor.cs index a47d54d..bc6887e 100644 --- a/ALttPRandomizer/Settings/CommonSettingsProcessor.cs +++ b/ALttPRandomizer/Settings/CommonSettingsProcessor.cs @@ -13,11 +13,16 @@ if (prop.Name == nameof(SeedSettings.PlayerName)) { continue; } + var value = prop.GetValue(settings) ?? throw new SettingsLookupException("settings.{0} not found", prop.Name); var valueFieldName = value.ToString() ?? throw new SettingsLookupException("settings.{0}.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 {0}.{1}", prop.PropertyType, valueFieldName); + if (prop.GetCustomAttributes().Any(att => att.HasRandomizer(randomizer))) { + continue; + } + if (!prop.GetCustomAttributes().Any(att => att.HasRandomizer(randomizer))) { var settingName = prop.GetCustomAttributes() @@ -30,7 +35,9 @@ } foreach (var att in fi.GetCustomAttributes().Where(att => att.HasRandomizer(randomizer))) { - yield return att.Setting; + foreach (var setting in att.Settings) { + yield return setting; + } } foreach (var att in fi.GetCustomAttributes().Where(att => att.HasRandomizer(randomizer))) { @@ -79,11 +86,7 @@ } } - public class SettingsLookupException : Exception { - public SettingsLookupException(string message, params object?[] args) : base(string.Format(message, args)) { } - } + public class SettingsLookupException(string message, params object?[] args) : Exception(string.Format(message, args)) { } - public class InvalidSettingsException : Exception { - public InvalidSettingsException(string message, params object?[] args) : base(string.Format(message, args)) { } - } + public class InvalidSettingsException(string message, params object?[] args) : Exception(string.Format(message, args)) { } } diff --git a/ALttPRandomizer/appsettings.Docker.json b/ALttPRandomizer/appsettings.Docker.json index 3dbe1af..d48cd73 100644 --- a/ALttPRandomizer/appsettings.Docker.json +++ b/ALttPRandomizer/appsettings.Docker.json @@ -1,7 +1,6 @@ { "ALttPRandomizer": { - "baserom": "/randomizer/alttp.sfc", - "pythonPath": "/usr/bin/python3", + "baserom": "/baserom/alttp.sfc", "flipsPath": "/flips/flips", "allowedCors": [ "https://new.alttpr.gwaa.kiwi", @@ -12,10 +11,19 @@ "clientId": "a48d5ae1-fa0a-4e33-9586-18c0eca0a28c", "blobstoreEndpoint": "https://alttprstorage.blob.core.windows.net/seeds" }, - "randomizerPaths": { - "base": "/randomizer", - "apr2025": "/apr2025_randomizer", - "dungeon_map": "/dungeon_map_randomizer" + "generators": { + "base": { + "workingDirectory": "/randomizer", + "randomizerCommand": [ "uv", "run", "DungeonRandomizer.py", "--bps", "--spoiler=json" ], + }, + "apr2025": { + "workingDirectory": "/apr2025_randomizer", + "randomizerCommand": [ "uv", "run", "EntranceRandomizer.py", "--json_spoiler" ], + }, + "beta": { + "workingDirectory": "/beta_randomizer", + "randomizerCommand": [ "uv", "run", "DungeonRandomizer.py", "--bps", "--spoiler=json" ], + }, } }, "Serilog": { diff --git a/Apr2025Randomizer b/Apr2025Randomizer index 84adf1d..ca9af42 160000 --- a/Apr2025Randomizer +++ b/Apr2025Randomizer @@ -1 +1 @@ -Subproject commit 84adf1dd89db9b1f3e4fd61b70aa7223aafae5db +Subproject commit ca9af423db90f6d606dd38d0bd3b4ab0571725e7 diff --git a/BetaRandomizer b/BetaRandomizer new file mode 160000 index 0000000..0f7253c --- /dev/null +++ b/BetaRandomizer @@ -0,0 +1 @@ +Subproject commit 0f7253c94ed0d354331634a9ef16d78521ec0347 diff --git a/Dockerfile b/Dockerfile index eee2cf3..82c427a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,37 +20,39 @@ EXPOSE 8080 EXPOSE 8081 RUN tdnf install -y python3 +RUN python3 -m ensurepip --default-pip --upgrade +RUN pip install uv RUN mkdir -p /flips COPY --from=build /flips/Flips-198/flips /flips/flips -RUN mkdir -p /randomizer/data -RUN touch /randomizer/data/base2current.json -RUN chown $APP_UID:$APP_UID /randomizer/data/base2current.json - -RUN mkdir -p /dungeon_map_randomizer/data -RUN touch /dungeon_map_randomizer/data/base2current.json -RUN chown $APP_UID:$APP_UID /dungeon_map_randomizer/data/base2current.json - -USER $APP_UID - -RUN python3 -m ensurepip --upgrade +COPY alttp.sfc /baserom/alttp.sfc +# base generator WORKDIR /randomizer -COPY alttp.sfc . -COPY BaseRandomizer/resources/app/meta/manifests/pip_requirements.txt requirements.txt -RUN python3 -m pip install -r requirements.txt +COPY BaseRandomizer/pyproject.toml . +RUN uv sync COPY BaseRandomizer/ . +# apr2025 generator WORKDIR /apr2025_randomizer + +COPY Apr2025Randomizer/pyproject.toml . +RUN uv sync + COPY Apr2025Randomizer/ . -WORKDIR /dungeon_map_randomizer +# beta generator +WORKDIR /beta_randomizer -COPY DungeonMapRandomizer/ . +COPY BetaRandomizer/pyproject.toml . +RUN uv sync +COPY BetaRandomizer/ . + +# web server WORKDIR /app COPY --from=build /app/publish . COPY ALttPRandomizer/appsettings.Docker.json appsettings.json diff --git a/DungeonMapRandomizer b/DungeonMapRandomizer deleted file mode 160000 index f2d07c9..0000000 --- a/DungeonMapRandomizer +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f2d07c98b72a341c50fa0e9f8ca5fab214f65b32