mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-21 05:43:42 -07:00
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:
parent
e2f1cebfb5
commit
fcf2141266
6 changed files with 98 additions and 94 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue