Fix JSON parsing every frame on file select (#3513)

* Fix JSON parsing every frame on file select

* string (#73)

---------

Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
This commit is contained in:
Garrett Cox 2023-12-17 02:40:09 +00:00 committed by GitHub
commit fcf2141266
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 98 additions and 94 deletions

View file

@ -94,6 +94,7 @@ void GameInteractor_SetTriforceHuntCreditsWarpActive(uint8_t state);
#include <vector> #include <vector>
#include <functional> #include <functional>
#include <string>
#define DEFINE_HOOK(name, type) \ #define DEFINE_HOOK(name, type) \
struct name { \ struct name { \
@ -193,6 +194,7 @@ public:
DEFINE_HOOK(OnSetGameLanguage, void()); DEFINE_HOOK(OnSetGameLanguage, void());
DEFINE_HOOK(OnFileDropped, void(std::string filePath));
DEFINE_HOOK(OnAssetAltChange, void()); DEFINE_HOOK(OnAssetAltChange, void());
// Helpers // Helpers

View file

@ -364,31 +364,16 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
#pragma GCC push_options #pragma GCC push_options
#pragma GCC optimize ("O0") #pragma GCC optimize ("O0")
bool Randomizer::SpoilerFileExists(const char* spoilerFileName) { bool Randomizer::SpoilerFileExists(const char* spoilerFileName) {
try { if (strcmp(spoilerFileName, "") != 0) {
if (strcmp(spoilerFileName, "") != 0) { std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName)); if (!spoilerFileStream) {
if (!spoilerFileStream) { return false;
return false; } else {
}
json spoilerFileJson;
spoilerFileStream >> spoilerFileJson;
if (!spoilerFileJson.contains("version") || !spoilerFileJson.contains("finalSeed")) {
return false;
}
return true; return true;
} }
return false;
} catch (std::exception& e) {
SPDLOG_ERROR("Error checking if spoiler file exists: {}", e.what());
return false;
} catch (...) {
SPDLOG_ERROR("Error checking if spoiler file exists");
return false;
} }
return false;
} }
#pragma GCC pop_options #pragma GCC pop_options
#pragma optimize("", on) #pragma optimize("", on)

View file

@ -118,6 +118,8 @@ CrowdControl* CrowdControl::Instance;
#include "soh/config/ConfigUpdaters.h" #include "soh/config/ConfigUpdaters.h"
void SoH_ProcessDroppedFiles(std::string filePath);
OTRGlobals* OTRGlobals::Instance; OTRGlobals* OTRGlobals::Instance;
SaveManager* SaveManager::Instance; SaveManager* SaveManager::Instance;
CustomMessageManager* CustomMessageManager::Instance; CustomMessageManager* CustomMessageManager::Instance;
@ -1057,6 +1059,11 @@ extern "C" void InitOTR() {
InitMods(); InitMods();
ActorDB::AddBuiltInCustomActors(); ActorDB::AddBuiltInCustomActors();
// #region SOH [Randomizer] TODO: Remove these and refactor spoiler file handling for randomizer
CVarClear("gRandomizerNewFileDropped");
CVarClear("gRandomizerDroppedFile");
// #endregion
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFileDropped>(SoH_ProcessDroppedFiles);
time_t now = time(NULL); time_t now = time(NULL);
tm *tm_now = localtime(&now); tm *tm_now = localtime(&now);
@ -1233,6 +1240,16 @@ extern "C" void Graph_StartFrame() {
} }
} }
#endif #endif
if (CVarGetInteger("gNewFileDropped", 0)) {
std::string filePath = SohUtils::Sanitize(CVarGetString("gDroppedFile", ""));
if (!filePath.empty()) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnFileDropped>(filePath);
}
CVarClear("gNewFileDropped");
CVarClear("gDroppedFile");
}
OTRGlobals::Instance->context->GetWindow()->StartFrame(); OTRGlobals::Instance->context->GetWindow()->StartFrame();
} }
@ -2580,70 +2597,74 @@ extern "C" void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* repla
gfx_register_blended_texture(name, mask, replacement); gfx_register_blended_texture(name, mask, replacement);
} }
// #region SOH [TODO] Ideally this should move to being event based, it's currently run every frame on the file select screen void SoH_ProcessDroppedFiles(std::string filePath) {
extern "C" void SoH_ProcessDroppedFiles() { try {
const char* droppedFile = CVarGetString("gDroppedFile", ""); std::ifstream configStream(filePath);
if (CVarGetInteger("gNewFileDropped", 0) && strcmp(droppedFile, "") != 0) { if (!configStream) {
try {
std::ifstream configStream(SohUtils::Sanitize(droppedFile));
if (!configStream) {
return;
}
nlohmann::json configJson;
configStream >> configJson;
if (!configJson.contains("CVars")) {
return;
}
clearCvars(enhancementsCvars);
clearCvars(cheatCvars);
clearCvars(randomizerCvars);
// Flatten everything under CVars into a single array
auto cvars = configJson["CVars"].flatten();
for (auto& [key, value] : cvars.items()) {
// Replace slashes with dots in key, and remove leading dot
std::string path = key;
std::replace(path.begin(), path.end(), '/', '.');
if (path[0] == '.') {
path.erase(0, 1);
}
if (value.is_string()) {
CVarSetString(path.c_str(), value.get<std::string>().c_str());
} else if (value.is_number_integer()) {
CVarSetInteger(path.c_str(), value.get<int>());
} else if (value.is_number_float()) {
CVarSetFloat(path.c_str(), value.get<float>());
}
}
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGuiWindow("Console")->Hide();
gui->GetGuiWindow("Actor Viewer")->Hide();
gui->GetGuiWindow("Collision Viewer")->Hide();
gui->GetGuiWindow("Save Editor")->Hide();
gui->GetGuiWindow("Display List Viewer")->Hide();
gui->GetGuiWindow("Stats")->Hide();
std::dynamic_pointer_cast<LUS::ConsoleWindow>(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->ClearBindings();
gui->SaveConsoleVariablesOnNextTick();
uint32_t finalHash = boost::hash_32<std::string>{}(configJson.dump());
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Configuration Loaded. Hash: %d", finalHash);
} catch (std::exception& e) {
SPDLOG_ERROR("Failed to load config file: {}", e.what());
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load config file");
return;
} catch (...) {
SPDLOG_ERROR("Failed to load config file");
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load config file");
return; return;
} }
nlohmann::json configJson;
configStream >> configJson;
// #region SOH [Randomizer] TODO: Refactor spoiler file handling for randomizer
if (configJson.contains("version") && configJson.contains("finalSeed")) {
CVarSetString("gRandomizerDroppedFile", filePath.c_str());
CVarSetInteger("gRandomizerNewFileDropped", 1);
return;
}
// #endregion
if (!configJson.contains("CVars")) {
return;
}
clearCvars(enhancementsCvars);
clearCvars(cheatCvars);
clearCvars(randomizerCvars);
// Flatten everything under CVars into a single array
auto cvars = configJson["CVars"].flatten();
for (auto& [key, value] : cvars.items()) {
// Replace slashes with dots in key, and remove leading dot
std::string path = key;
std::replace(path.begin(), path.end(), '/', '.');
if (path[0] == '.') {
path.erase(0, 1);
}
if (value.is_string()) {
CVarSetString(path.c_str(), value.get<std::string>().c_str());
} else if (value.is_number_integer()) {
CVarSetInteger(path.c_str(), value.get<int>());
} else if (value.is_number_float()) {
CVarSetFloat(path.c_str(), value.get<float>());
}
}
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGuiWindow("Console")->Hide();
gui->GetGuiWindow("Actor Viewer")->Hide();
gui->GetGuiWindow("Collision Viewer")->Hide();
gui->GetGuiWindow("Save Editor")->Hide();
gui->GetGuiWindow("Display List Viewer")->Hide();
gui->GetGuiWindow("Stats")->Hide();
std::dynamic_pointer_cast<LUS::ConsoleWindow>(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->ClearBindings();
gui->SaveConsoleVariablesOnNextTick();
uint32_t finalHash = boost::hash_32<std::string>{}(configJson.dump());
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Configuration Loaded. Hash: %d", finalHash);
} catch (std::exception& e) {
SPDLOG_ERROR("Failed to load config file: {}", e.what());
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load config file");
return;
} catch (...) {
SPDLOG_ERROR("Failed to load config file");
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load config file");
return;
} }
} }
// #endregion // #endregion

View file

@ -175,7 +175,6 @@ void EntranceTracker_SetLastEntranceOverride(s16 entranceIndex);
void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement); void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* replacement);
void SaveManager_ThreadPoolWait(); void SaveManager_ThreadPoolWait();
void CheckTracker_OnMessageClose(); void CheckTracker_OnMessageClose();
void SoH_ProcessDroppedFiles();
int32_t GetGIID(uint32_t itemID); int32_t GetGIID(uint32_t itemID);
#endif #endif

View file

@ -1030,18 +1030,18 @@ void FileChoose_UpdateRandomizer() {
fileSelectSpoilerFileLoaded = false; fileSelectSpoilerFileLoaded = false;
} }
if ((CVarGetInteger("gNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0) || if ((CVarGetInteger("gRandomizerNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0) ||
(!fileSelectSpoilerFileLoaded && SpoilerFileExists(CVarGetString("gSpoilerLog", "")))) { (!fileSelectSpoilerFileLoaded && SpoilerFileExists(CVarGetString("gSpoilerLog", "")))) {
if (CVarGetInteger("gNewFileDropped", 0) != 0) { if (CVarGetInteger("gRandomizerNewFileDropped", 0) != 0) {
CVarSetString("gSpoilerLog", CVarGetString("gDroppedFile", "None")); CVarSetString("gSpoilerLog", CVarGetString("gRandomizerDroppedFile", "None"));
} }
bool silent = true; bool silent = true;
if ((CVarGetInteger("gNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0)) { if ((CVarGetInteger("gRandomizerNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0)) {
silent = false; silent = false;
} }
CVarSetInteger("gNewSeedGenerated", 0); CVarSetInteger("gNewSeedGenerated", 0);
CVarSetInteger("gNewFileDropped", 0); CVarSetInteger("gRandomizerNewFileDropped", 0);
CVarSetString("gDroppedFile", ""); CVarSetString("gRandomizerDroppedFile", "");
fileSelectSpoilerFileLoaded = false; fileSelectSpoilerFileLoaded = false;
const char* fileLoc = CVarGetString("gSpoilerLog", ""); const char* fileLoc = CVarGetString("gSpoilerLog", "");
Randomizer_LoadSettings(fileLoc); Randomizer_LoadSettings(fileLoc);
@ -1076,7 +1076,6 @@ void FileChoose_UpdateMainMenu(GameState* thisx) {
Input* input = &this->state.input[0]; Input* input = &this->state.input[0];
bool dpad = CVarGetInteger("gDpadText", 0); bool dpad = CVarGetInteger("gDpadText", 0);
SoH_ProcessDroppedFiles();
FileChoose_UpdateRandomizer(); FileChoose_UpdateRandomizer();
if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_A)) { if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_A)) {
@ -1267,7 +1266,6 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) {
s8 i = 0; s8 i = 0;
bool dpad = CVarGetInteger("gDpadText", 0); bool dpad = CVarGetInteger("gDpadText", 0);
SoH_ProcessDroppedFiles();
FileChoose_UpdateRandomizer(); FileChoose_UpdateRandomizer();
if (ABS(this->stickRelX) > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT | BTN_DRIGHT))) { if (ABS(this->stickRelX) > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT | BTN_DRIGHT))) {

View file

@ -456,7 +456,6 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
this->prevConfigMode = CM_MAIN_MENU; this->prevConfigMode = CM_MAIN_MENU;
this->configMode = CM_NAME_ENTRY_TO_MAIN; this->configMode = CM_NAME_ENTRY_TO_MAIN;
CVarSetInteger("gOnFileSelectNameEntry", 0); CVarSetInteger("gOnFileSelectNameEntry", 0);
CVarSetInteger("gNewFileDropped", 0);
this->nameBoxAlpha[this->buttonIndex] = this->nameAlpha[this->buttonIndex] = 200; this->nameBoxAlpha[this->buttonIndex] = this->nameAlpha[this->buttonIndex] = 200;
this->connectorAlpha[this->buttonIndex] = 255; this->connectorAlpha[this->buttonIndex] = 255;
func_800AA000(300.0f, 0xB4, 0x14, 0x64); func_800AA000(300.0f, 0xB4, 0x14, 0x64);