Avoid randomizer generation races with file select (#7136)

Fixes both starting file while generating,
& starting generation in file loading transition

Remove RandoGenerating cvar
This commit is contained in:
Philip Dubé
2026-08-31 14:04:50 +00:00
committed by GitHub
parent 2dd51f1288
commit a7cd6c8113
9 changed files with 40 additions and 30 deletions
-1
View File
@@ -5,7 +5,6 @@
void BootCommands_Init() {
// Clears vars to prevent randomizer menu from being disabled
CVarClear(CVAR_GENERAL("RandoGenerating")); // Clear when a crash happened during rando seed generation
CVarClear(CVAR_GENERAL("NewSeedGenerated"));
CVarClear(CVAR_GENERAL("OnFileSelectNameEntry")); // Clear when soh is killed on the file name entry page
CVarClear(CVAR_GENERAL("BetterDebugWarpScreenMQMode"));
+16 -17
View File
@@ -1,3 +1,4 @@
#include <atomic>
#include <fstream>
#include <sstream>
#include <tuple>
@@ -43,7 +44,7 @@ std::unordered_map<std::string, HintType> SpoilerfileHintTypeNameToEnum;
std::set<RandomizerCheck> excludedLocations;
std::set<RandomizerCheck> spoilerExcludedLocations;
bool generated;
static std::atomic<bool> randoGenerating;
bool Rando_HandleSpoilerDrop(char* filePath) {
if (SohUtils::IsStringEmpty(filePath)) {
@@ -926,8 +927,6 @@ RandomizerCheck Randomizer::GetCheckFromRandomizerInf(RandomizerInf randomizerIn
std::thread randoThread;
void GenerateRandomizerImgui(std::string seed = "") {
CVarSetInteger(CVAR_GENERAL("RandoGenerating"), 1);
Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
auto ctx = Rando::Context::GetInstance();
// RANDOTODO proper UI for selecting if a spoiler loaded should be used for settings
Rando::Settings::GetInstance()->SetAllToContext();
@@ -963,32 +962,32 @@ void GenerateRandomizerImgui(std::string seed = "") {
}
Rando::Context::GetInstance()->SetSeedGenerated(GenerateRandomizer(excludedLocations, enabledTricks, seed));
CVarSetInteger(CVAR_GENERAL("RandoGenerating"), 0);
Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
generated = true;
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnGenerationCompletion>();
randoGenerating = false;
}
bool IsRandoGenerating() {
return randoGenerating;
}
bool GenerateRandomizer(std::string seed /*= ""*/) {
if (generated) {
generated = false;
randoThread.join();
if (randoGenerating) {
return false;
}
if (CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) == 0) {
randoThread = std::thread(&GenerateRandomizerImgui, seed);
return true;
}
return false;
WaitForRandoGeneration();
randoGenerating = true;
randoThread = std::thread(&GenerateRandomizerImgui, seed);
return true;
}
static bool locationsTabOpen = false;
static bool tricksTabOpen = false;
void JoinRandoGenerationThread() {
if (generated) {
generated = false;
void WaitForRandoGeneration() {
if (randoThread.joinable()) {
randoThread.join();
}
}
+2 -1
View File
@@ -44,7 +44,8 @@ extern "C" {
#endif
bool GenerateRandomizer(std::string seed = "");
void JoinRandoGenerationThread();
bool IsRandoGenerating();
void WaitForRandoGeneration();
#ifdef __cplusplus
}
+8
View File
@@ -2418,6 +2418,14 @@ extern "C" uint8_t Randomizer_GenerateRandomizer() {
return GenerateRandomizer() ? 1 : 0;
}
extern "C" bool Randomizer_IsGenerating() {
return IsRandoGenerating();
}
extern "C" void Randomizer_WaitForGeneration() {
WaitForRandoGeneration();
}
extern "C" void Randomizer_ShowRandomizerMenu() {
SohGui::ShowRandomizerSettingsMenu();
}
+2
View File
@@ -123,6 +123,8 @@ uint8_t Randomizer_IsSeedGenerated();
uint8_t Randomizer_IsSpoilerLoaded();
void Randomizer_SetSpoilerLoaded(bool spoilerLoaded);
uint8_t Randomizer_GenerateRandomizer();
bool Randomizer_IsGenerating();
void Randomizer_WaitForGeneration();
void Randomizer_ShowRandomizerMenu();
GetItemEntry ItemTable_Retrieve(int16_t getItemID);
GetItemEntry ItemTable_RetrieveEntry(s16 modIndex, s16 getItemID);
+4 -7
View File
@@ -71,7 +71,7 @@ void DrawLocationsMenu(WidgetInfo& info) {
int32_t currMQDungeonSetting = CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), 0) |
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 0) << 8;
static ImVec2 cellPadding(8.0f, 8.0f);
bool generating = CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0);
bool generating = IsRandoGenerating();
bool disableEditingRandoSettings = generating || CVarGetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0);
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0) || disableEditingRandoSettings);
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding);
@@ -363,7 +363,7 @@ void DrawTricksMenu(WidgetInfo& info) {
auto ctx = Rando::Context::GetInstance();
auto randoSettings = Rando::Settings::GetInstance();
static ImVec2 cellPadding(8.0f, 8.0f);
bool generating = CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0);
bool generating = IsRandoGenerating();
bool disableEditingRandoSettings = generating || CVarGetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0);
if (tricksDirty) {
tricksDirty = false;
@@ -729,18 +729,15 @@ void SohMenu::AddMenuRandomizer() {
AddWidget(path, "Randomize All Settings", WIDGET_BUTTON)
.Callback([](WidgetInfo& info) { Rando::Settings::GetInstance()->RandomizeAllSettings(); })
.PreFunc([](WidgetInfo& info) {
info.options->disabled = CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) ||
CVarGetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0);
info.options->disabled = IsRandoGenerating() || CVarGetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0);
})
.Options(ButtonOptions()
.Size(ImVec2(250.f, 0.f))
.Tooltip("Randomizes all randomizer settings to random valid values (excludes tricks)."))
.SameLine(true);
AddWidget(path, "Spoiler File", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) {
JoinRandoGenerationThread();
if (!CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) {
std::string spoilerfilepath = CVarGetString(CVAR_GENERAL("SpoilerLog"), "");
ImGui::Text("Spoiler File: %s", spoilerfilepath.c_str());
ImGui::Text("Spoiler File: %s", CVarGetString(CVAR_GENERAL("SpoilerLog"), ""));
}
});
+2 -1
View File
@@ -7,6 +7,7 @@
#include "soh/SohGui/ImGuiUtils.h"
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
#include "soh/Enhancements/randomizer/randomizer.h"
#include "soh/Enhancements/randomizer/settings.h"
namespace SohGui {
@@ -144,7 +145,7 @@ static void StartingItemCombobox(RandomizerSettingKey rsk) {
}
void DrawStartingItemsMenu(WidgetInfo& info) {
bool generating = CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0);
bool generating = IsRandoGenerating();
bool disableEditingRandoSettings = generating || CVarGetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0);
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0) || disableEditingRandoSettings);
-1
View File
@@ -12,7 +12,6 @@ struct Migration {
static const Migration version3Migrations[] = {
{ "gSwitchAge", "gGeneral.SwitchAge" },
{ "gFrameAdvance", "gDeveloperTools.FrameAdvanceTick" },
{ "gRandoGenerating", "gGeneral.RandoGenerating" },
{ "gNewSeedGenerated", "gGeneral.NewSeedGenerated" },
{ "gOnFileSelectNameEntry", "gGeneral.OnFileSelectNameEntry" },
{ "gBetterDebugWarpScreenMQMode", "gGeneral.BetterDebugWarpScreenMQMode" },
@@ -389,11 +389,11 @@ int retries = 0;
bool fileSelectSpoilerFileLoaded = false;
void FileChoose_UpdateRandomizer() {
if (CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) != 0 && generating == 0) {
if (Randomizer_IsGenerating() && generating == 0) {
generating = 1;
Audio_PlaySequenceWithSeqPlayerIO(SEQ_PLAYER_BGM_MAIN, NA_BGM_HORSE, 0, 7, 1);
return;
} else if (CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) == 0 && generating) {
} else if (!Randomizer_IsGenerating() && generating) {
if (Randomizer_IsSeedGenerated()) {
Audio_PlayFanfare(NA_BGM_HORSE_GOAL);
retries = 0;
@@ -463,6 +463,9 @@ void FileChoose_UpdateMainMenu(GameState* thisx) {
u8 isDefaultNameOptionSet;
FileChoose_UpdateRandomizer();
if (generating) {
return;
}
if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_A)) {
if (this->buttonIndex <= FS_BTN_MAIN_FILE_3) {
@@ -2544,6 +2547,7 @@ void FileChoose_LoadGame(GameState* thisx) {
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
gSaveContext.fileNum = this->buttonIndex;
gSaveContext.gameMode = GAMEMODE_NORMAL;
Randomizer_WaitForGeneration();
if ((this->buttonIndex == FS_BTN_SELECT_FILE_1 && CVarGetInteger(CVAR_DEVELOPER_TOOLS("DebugEnabled"), 0)) ||
this->buttonIndex == 0xFF) {