diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 751ad0b0f..9cadc7320 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -178,6 +178,20 @@ typedef struct ShipQuestSaveContextData { ShipQuestSpecificSaveContextData data; } ShipQuestSaveContextData; +typedef struct ArchipelagoLocationData { + char itemName[100]; + char locationName[100]; + char playerName[17]; + u8 flags; +} ArchipelagoLocationData; + +typedef struct ArchipelagoData { + char roomHash[100]; + char slotName[17]; + u32 lastReceivedItemIndex; + ArchipelagoLocationData locations[RC_MAX]; +} ArchipelagoData; + typedef struct ShipSaveContextData { u16 pendingSale; u16 pendingSaleMod; @@ -185,6 +199,7 @@ typedef struct ShipSaveContextData { SohStats stats; FaroresWindData backupFW; ShipQuestSaveContextData quest; + ArchipelagoData apData; u8 maskMemory; u8 filenameLanguage; //TODO: Move non-rando specific flags to a new sohInf and move the remaining randomizerInf to ShipRandomizerSaveContextData @@ -314,12 +329,14 @@ typedef enum { /* 01 */ QUEST_MASTER, /* 02 */ QUEST_RANDOMIZER, /* 03 */ QUEST_BOSSRUSH, + /* 03 */ QUEST_ARCHIPELAGO, } Quest; #define IS_VANILLA (gSaveContext.ship.quest.id == QUEST_NORMAL) #define IS_MASTER_QUEST (gSaveContext.ship.quest.id == QUEST_MASTER) #define IS_RANDO (gSaveContext.ship.quest.id == QUEST_RANDOMIZER) #define IS_BOSS_RUSH (gSaveContext.ship.quest.id == QUEST_BOSSRUSH) +#define IS_ARCHIPELAGO (gSaveContext.ship.quest.id == QUEST_ARCHIPELAGO) typedef enum { /* 0x00 */ BTN_ENABLED, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 604bf99b4..6689e3e0a 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -309,7 +309,7 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() { RandomizerCheck rc = randomizerQueuedChecks.front(); auto loc = Rando::Context::GetInstance()->GetItemLocation(rc); - if(rc == RC_ARCHIPELAGO_RECIEVED_ITEM) { + if (rc == RC_ARCHIPELAGO_RECIEVED_ITEM) { getItemEntry = Rando::Context::GetInstance()->GetArchipelagoGIEntry(); } else { RandomizerGet vanillaRandomizerGet = Rando::StaticData::GetLocation(rc)->GetVanillaItem(); @@ -384,7 +384,7 @@ void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) { // let arhipelago know we got this check if(randomizerQueuedCheck != RC_ARCHIPELAGO_RECIEVED_ITEM) { ArchipelagoClient& ap_client = ArchipelagoClient::GetInstance(); - ap_client.check_location(randomizerQueuedCheck); + ap_client.CheckLocation(randomizerQueuedCheck); } loc->SetCheckStatus(RCSHOW_COLLECTED); diff --git a/soh/soh/Network/Archipelago/Archipelago.cpp b/soh/soh/Network/Archipelago/Archipelago.cpp index c8928869b..eb2d221cb 100644 --- a/soh/soh/Network/Archipelago/Archipelago.cpp +++ b/soh/soh/Network/Archipelago/Archipelago.cpp @@ -16,10 +16,10 @@ ArchipelagoClient::ArchipelagoClient() { std::string uuid = ap_get_uuid("uuid"); ItemRecievedCallback = nullptr; - game_won = false; + gameWon = false; namespace apc = AP_Client_consts; - CVarSetInteger("ArchipelagoConnected", 0); + CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0); // call poll every frame GameInteractor::Instance->RegisterGameHook([](){ArchipelagoClient::GetInstance().Poll();}); @@ -46,6 +46,11 @@ bool ArchipelagoClient::StartClient() { 0b001, tags); }); + apClient->set_slot_connected_handler([&](const nlohmann::json) { + ArchipelagoConsole_SendMessage("[LOG] Connected.", false); + ArchipelagoClient::StartLocationScouts(); + }); + apClient->set_items_received_handler([&](const std::list& items) { for(const APClient::NetworkItem& item : items) { OnItemReceived(item.item, false); // todo get rid of notify, since it doesn't work for us right now anyway @@ -71,8 +76,10 @@ bool ArchipelagoClient::StartClient() { std::string logMessage = "[LOG] Location scouted: " + itemName + " for " + playerName + " in location " + locationName; ArchipelagoConsole_SendMessage(logMessage.c_str()); } - + + ArchipelagoConsole_SendMessage("[LOG] Scouting finished."); }); // todo maybe move these functions to a lambda, since they don't have to be static anymore + apClient->set_location_checked_handler([&](const std::list locations) { // todo implement me }); @@ -97,7 +104,7 @@ bool ArchipelagoClient::IsConnected() { return apClient->get_state() == APClient::State::SLOT_CONNECTED; } -void ArchipelagoClient::check_location(RandomizerCheck SoH_check_id) { +void ArchipelagoClient::CheckLocation(RandomizerCheck SoH_check_id) { //std::string_view ap_name = Rando::StaticData::SohCheckToAP[SoH_check_id]; std::string ap_name = Rando::StaticData::GetLocation(SoH_check_id)->GetName(); if(ap_name.empty()) { @@ -122,14 +129,6 @@ void ArchipelagoClient::RemoveItemRecievedCallback(std::functionget_item_name(recieved_item_id, AP_Client_consts::AP_GAME_NAME); @@ -142,9 +141,9 @@ void ArchipelagoClient::OnItemReceived(int64_t recieved_item_id, bool notify_pla } void ArchipelagoClient::SendGameWon() { - if(!game_won) { + if(!gameWon) { apClient->StatusUpdate(APClient::ClientStatus::GOAL); - game_won = true; + gameWon = true; } } diff --git a/soh/soh/Network/Archipelago/Archipelago.h b/soh/soh/Network/Archipelago/Archipelago.h index c5f6d9819..838dd748e 100644 --- a/soh/soh/Network/Archipelago/Archipelago.h +++ b/soh/soh/Network/Archipelago/Archipelago.h @@ -39,7 +39,7 @@ class ArchipelagoClient{ const std::vector& GetScoutedItems(); bool IsConnected(); - void check_location(RandomizerCheck SoH_check_id); + void CheckLocation(RandomizerCheck SoH_check_id); // callback slots void AddItemRecievedCallback(std::function callback); @@ -65,19 +65,17 @@ class ArchipelagoClient{ static std::shared_ptr instance; // is this even used? static bool initialized; - bool game_won; + bool gameWon; std::map slotData; std::set locations; std::vector scoutedItems; - // callback functions - void OnConnected(); - + // Callback Functions void OnLocationChecked(int64_t location_id); void OnDeathLinkReceived() { }; // TODO: implement me - // callbacks + // Callbacks std::function ItemRecievedCallback; }; diff --git a/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.cpp b/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.cpp index 744099ebe..75e359839 100644 --- a/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.cpp +++ b/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.cpp @@ -9,14 +9,16 @@ bool autoScroll = true; using namespace UIWidgets; -void ArchipelagoConsole_SendMessage(const char* fmt, ...) { - char buf[1024]; - va_list args; - va_start(args, fmt); - vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); - buf[IM_ARRAYSIZE(buf) - 1] = 0; - va_end(args); - Items.push_back(strdup(buf)); +void ArchipelagoConsole_SendMessage(const char* fmt, bool debugMessage, ...) { + if (!debugMessage || CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("DebugEnabled"), 0)) { + char buf[1024]; + va_list args; + va_start(args, fmt); + vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); + buf[IM_ARRAYSIZE(buf) - 1] = 0; + va_end(args); + Items.push_back(strdup(buf)); + } } void ArchipelagoConsoleWindow::DrawElement() { @@ -60,11 +62,4 @@ void ArchipelagoConsoleWindow::DrawElement() { ImGui::EndChild(); ImGui::PopStyleColor(); ImGui::PopStyleVar(2); - - if (UIWidgets::Button("Add dummy lines to log", - UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.0, 0.0)))) { - ArchipelagoConsole_SendMessage("[LOG] Hello World"); - ArchipelagoConsole_SendMessage("[ERROR] Hello World"); - ArchipelagoConsole_SendMessage("Hello World"); - } }; diff --git a/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.h b/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.h index 602dee2db..9856969df 100644 --- a/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.h +++ b/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.h @@ -15,6 +15,6 @@ class ArchipelagoConsoleWindow final : public Ship::GuiWindow { void UpdateElement() override {}; }; -void ArchipelagoConsole_SendMessage(const char* fmt, ...); +void ArchipelagoConsole_SendMessage(const char* fmt, bool debugMessage = true, ...); #endif // ARCHIPELAGO_CONSOLE_WINDOW_H \ No newline at end of file diff --git a/soh/soh/Network/Archipelago/ArchipelagoSettingsWindow.cpp b/soh/soh/Network/Archipelago/ArchipelagoSettingsWindow.cpp index d252384ff..cc561a720 100644 --- a/soh/soh/Network/Archipelago/ArchipelagoSettingsWindow.cpp +++ b/soh/soh/Network/Archipelago/ArchipelagoSettingsWindow.cpp @@ -38,24 +38,31 @@ void ArchipelagoSettingsWindow::DrawElement() { if (UIWidgets::Button("Connect", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.0, 0.0)))) { bool success = AP_client.StartClient(); - ArchipelagoConsole_SendMessage("[LOG] Trying to connect..."); + ArchipelagoConsole_SendMessage("[LOG] Trying to connect...", false); } ImGui::SameLine(); ImGui::Text(ArchipelagoClient::GetInstance().GetConnectionStatus()); - // Temporary developer helpers - ImGui::SeparatorText("Developer Tools"); - if (UIWidgets::Button("Scout", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.0, 0.0)))) { - AP_client.StartLocationScouts(); - } - ImGui::SameLine(); - if (UIWidgets::Button("Link up", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.0, 0.0)))) { - CVarSetInteger("ArchipelagoConnected", 1); - } - ImGui::SameLine(); - if (UIWidgets::Button("Give Blue Rupee", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.0, 0.0)))) { - ArchipelagoClient::GetInstance().OnItemReceived(66077, true); - } + UIWidgets::CVarCheckbox( + "Debug Enabled", CVAR_REMOTE_ARCHIPELAGO("DebugEnabled"), + UIWidgets::CheckboxOptions().Color(THEME_COLOR).Tooltip("Enable Archipelago debug tools and extra logging.")); + // Temporary developer helpers + UIWidgets::Separator(); + if (CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("DebugEnabled"), 0)) { + ImGui::SeparatorText("Developer Tools"); + if (UIWidgets::Button("Scout", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.0, 0.0)))) { + AP_client.StartLocationScouts(); + } + ImGui::SameLine(); + if (UIWidgets::Button("Link up", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.0, 0.0)))) { + CVarSetInteger("ArchipelagoConnected", 1); + } + ImGui::SameLine(); + if (UIWidgets::Button("Give Blue Rupee", + UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.0, 0.0)))) { + ArchipelagoClient::GetInstance().OnItemReceived(66077, true); + } + } }; diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index c3fef9a8e..d817ddec9 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -1075,7 +1075,7 @@ void FileChoose_UpdateRandomizer() { } } - if (CVarGetInteger("ArchipelagoConnected", 0) && !fileSelectArchipelagoLoaded) { + if (CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0) && !fileSelectArchipelagoLoaded) { ParseArchipelago(); fileSelectArchipelagoLoaded = true; Audio_PlayFanfare(NA_BGM_HORSE_GOAL);