From 603c1631678b32def9efe99142f0afe8a8bd8179 Mon Sep 17 00:00:00 2001 From: Jerom Venneker Date: Sun, 25 May 2025 21:17:44 +0200 Subject: [PATCH 1/3] Rework Item Queue, Repeated connections should no longer give multiple copies of the same item --- soh/soh/Network/Archipelago/Archipelago.cpp | 47 +++++++++++++++---- soh/soh/Network/Archipelago/Archipelago.h | 9 ++-- .../Archipelago/ArchipelagoSettingsWindow.cpp | 8 +++- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/soh/soh/Network/Archipelago/Archipelago.cpp b/soh/soh/Network/Archipelago/Archipelago.cpp index 7a5b4bd475..7f52b5a131 100644 --- a/soh/soh/Network/Archipelago/Archipelago.cpp +++ b/soh/soh/Network/Archipelago/Archipelago.cpp @@ -30,6 +30,7 @@ ArchipelagoClient::ArchipelagoClient() { namespace apc = AP_Client_consts; CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0); + bool itemQueued = false; // call poll every frame COND_HOOK(GameInteractor::OnGameFrameUpdate, true, [](){ArchipelagoClient::GetInstance().Poll();}); @@ -73,7 +74,14 @@ bool ArchipelagoClient::StartClient() { apClient->set_items_received_handler([&](const std::list& items) { for(const APClient::NetworkItem& item : items) { - OnItemReceived(item.item, item.index); + ApItem apItem; + const std::string game = apClient->get_player_game(item.player); + apItem.itemName = apClient->get_item_name(item.item, game); + apItem.locationName = apClient->get_location_name(item.location, game); + apItem.playerName = apClient->get_player_alias(item.player); + apItem.flags = item.flags; + apItem.index = item.index; + OnItemReceived(apItem); } }); @@ -187,23 +195,37 @@ void ArchipelagoClient::CheckLocation(RandomizerCheck sohCheckId) { apClient->LocationChecks({ apItemId }); } -void ArchipelagoClient::OnItemReceived(int64_t apItemId, int64_t itemIndex) { +void ArchipelagoClient::OnItemReceived(const ApItem apItem) { if(!GameInteractor::IsSaveLoaded(true)) { // Don't queue up any items when we aren't in game // Any Items missed this way will get synched when we load the save return; } - if(itemIndex < gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex) { - // Skip recieving any items we already have + std::string logMessage = "[Log] Recieved " + apItem.itemName; + ArchipelagoConsole_SendMessage(logMessage.c_str()); + + // add item to the queue + recieveQueue.push(apItem); +} + +void ArchipelagoClient::QueueItem(const ApItem item) { + if(item.index < gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex) { + // Skip queueing any items we already have + std::string logMessage = "[Log] Skipping giving " + item.itemName + ". We recieved this previously."; + ArchipelagoConsole_SendMessage(logMessage.c_str()); return; } - const std::string item_name = apClient->get_item_name(apItemId, AP_Client_consts::AP_GAME_NAME); - std::string logMessage = "[Log] Recieved " + item_name; + std::string logMessage = "[Log] Giving " + item.itemName; ArchipelagoConsole_SendMessage(logMessage.c_str()); - const RandomizerGet item = Rando::StaticData::itemNameToEnum[item_name]; - GameInteractor_ExecuteOnArchipelagoItemRecieved(static_cast(item)); + const RandomizerGet RG = Rando::StaticData::itemNameToEnum[item.itemName]; + if(RG == RG_NONE) { + return; + } + + itemQueued = true; + GameInteractor_ExecuteOnArchipelagoItemRecieved(static_cast(RG)); } void ArchipelagoClient::SendGameWon() { @@ -217,6 +239,14 @@ void ArchipelagoClient::Poll() { if(apClient == nullptr) { return; } + + // queue another item to be recieved + if(!itemQueued && recieveQueue.size() > 0) { + + const ApItem item = recieveQueue.front(); + recieveQueue.pop(); + QueueItem(item); + } apClient->poll(); } @@ -369,6 +399,7 @@ void RegisterArchipelago() { [](uint32_t rc) { if (rc == RC_ARCHIPELAGO_RECIEVED_ITEM) { gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex++; + ArchipelagoClient::GetInstance().itemQueued = false; } else { ArchipelagoClient::GetInstance().CheckLocation((RandomizerCheck)rc); } diff --git a/soh/soh/Network/Archipelago/Archipelago.h b/soh/soh/Network/Archipelago/Archipelago.h index 6967d7e14c..e077125e7c 100644 --- a/soh/soh/Network/Archipelago/Archipelago.h +++ b/soh/soh/Network/Archipelago/Archipelago.h @@ -3,6 +3,7 @@ #include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/Enhancements/randomizer/static_data.h" #include +#include // Forward declaration class APClient; @@ -22,7 +23,7 @@ class ArchipelagoClient{ std::string locationName; std::string playerName; unsigned int flags; - int index; + uint64_t index; }; static ArchipelagoClient& GetInstance(); @@ -46,14 +47,15 @@ class ArchipelagoClient{ bool IsConnected(); void CheckLocation(RandomizerCheck SoH_check_id); - // todo move me back down when done testing - void OnItemReceived(int64_t apItemId, int64_t itemIndex); + void OnItemReceived(const ApItem apItem); + void QueueItem(const ApItem item); void SendGameWon(); void Poll(); std::unique_ptr apClient; + bool itemQueued; protected: ArchipelagoClient(); @@ -71,6 +73,7 @@ class ArchipelagoClient{ std::map slotData; std::set locations; std::vector scoutedItems; + std::queue recieveQueue; }; void LoadArchipelagoData(); diff --git a/soh/soh/Network/Archipelago/ArchipelagoSettingsWindow.cpp b/soh/soh/Network/Archipelago/ArchipelagoSettingsWindow.cpp index 10902419fc..05ae198b3c 100644 --- a/soh/soh/Network/Archipelago/ArchipelagoSettingsWindow.cpp +++ b/soh/soh/Network/Archipelago/ArchipelagoSettingsWindow.cpp @@ -63,7 +63,13 @@ void ArchipelagoSettingsWindow::DrawElement() { ImGui::SameLine(); if (UIWidgets::Button("Give Blue Rupee", UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.0, 0.0)))) { - ArchipelagoClient::GetInstance().OnItemReceived(16711816, true); + ArchipelagoClient::ApItem apItem; + apItem.itemName = "Blue Rupee"; + apItem.locationName = "Nowhere"; + apItem.playerName = "Nobody"; + apItem.flags = 0b001; + apItem.index = 999999; + ArchipelagoClient::GetInstance().OnItemReceived(apItem); } } }; From f6359f10085be70a55f69ab07b85286c9a4032f1 Mon Sep 17 00:00:00 2001 From: Jerom Venneker Date: Mon, 26 May 2025 20:51:49 +0200 Subject: [PATCH 2/3] Added opening of local checks when synchinc locations --- .../game-interactor/GameInteractor_HookTable.h | 3 ++- .../game-interactor/GameInteractor_Hooks.cpp | 8 ++++++-- .../game-interactor/GameInteractor_Hooks.h | 3 ++- soh/soh/Enhancements/randomizer/hook_handlers.cpp | 7 +++++-- soh/soh/Network/Archipelago/Archipelago.cpp | 12 ++++++++++-- soh/soh/Network/Archipelago/Archipelago.h | 1 + 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h index 6066c906cd..c0c3672daa 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h @@ -71,4 +71,5 @@ DEFINE_HOOK(OnAssetAltChange, ()); DEFINE_HOOK(OnKaleidoUpdate, ()); DEFINE_HOOK(OnRandomizerItemGivenHooks, (uint32_t rc)); -DEFINE_HOOK(OnArchipelagoItemRecieved, (uint32_t rc)); +DEFINE_HOOK(OnArchipelagoItemRecieved, (uint32_t rg)); +DEFINE_HOOK(OnRandomizerExternalCheck, (uint32_t rc)); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index c1bc5e17d3..393df5b2c1 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -309,6 +309,10 @@ void GameInteractor_ExecuteOnRandomizerItemGivenHooks(uint32_t rc) { } // MARK: Archipelago -void GameInteractor_ExecuteOnArchipelagoItemRecieved(uint32_t rc) { - GameInteractor::Instance->ExecuteHooks(rc); +void GameInteractor_ExecuteOnArchipelagoItemRecieved(uint32_t rg) { + GameInteractor::Instance->ExecuteHooks(rg); +} + +void GameInteractor_ExecuteOnRandomizerExternalCheck(uint32_t rc) { + GameInteractor::Instance->ExecuteHooks(rc); } diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index 8a1f136089..da276455a9 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -85,7 +85,8 @@ void GameInteractor_ExecuteOnKaleidoUpdate(); void GameInteractor_ExecuteOnRandomizerItemGivenHooks(uint32_t rc); // Mark: - Archipelago -void GameInteractor_ExecuteOnArchipelagoItemRecieved(uint32_t rc); +void GameInteractor_ExecuteOnArchipelagoItemRecieved(uint32_t rg); +void GameInteractor_ExecuteOnRandomizerExternalCheck(uint32_t rc); #ifdef __cplusplus } diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index a9b209b7b3..f21a593128 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -286,6 +286,10 @@ void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t randomizerQueuedChecks.push(rc); } +void RandomizerOnExternalCheckHandler(uint32_t randomizerCheck) { + randomizerQueuedChecks.push(static_cast(randomizerCheck)); +} + static Vec3f spawnPos = { 0.0f, -999.0f, 0.0f }; void RandomizerOnPlayerUpdateForRCQueueHandler() { @@ -2525,9 +2529,8 @@ void RandomizerRegisterHooks() { onCuccoOrChickenHatchHook = GameInteractor::Instance->RegisterGameHook( RandomizerOnCuccoOrChickenHatch); - // TODO Implement propeerly when we can read what kind of game we're playing from the save file - COND_HOOK(GameInteractor::OnArchipelagoItemRecieved, IS_ARCHIPELAGO, ArchipelagoOnRecieveItem); + COND_HOOK(GameInteractor::OnRandomizerExternalCheck, IS_ARCHIPELAGO, RandomizerOnExternalCheckHandler) if (RAND_GET_OPTION(RSK_FISHSANITY) != RO_FISHSANITY_OFF) { OTRGlobals::Instance->gRandoContext->GetFishsanity()->InitializeFromSave(); diff --git a/soh/soh/Network/Archipelago/Archipelago.cpp b/soh/soh/Network/Archipelago/Archipelago.cpp index 7f52b5a131..a33ea6a99c 100644 --- a/soh/soh/Network/Archipelago/Archipelago.cpp +++ b/soh/soh/Network/Archipelago/Archipelago.cpp @@ -109,7 +109,9 @@ bool ArchipelagoClient::StartClient() { }); // 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 + for(const int64_t apLoc : locations) { + QueueExternalCheck(apLoc); + } }); return true; @@ -171,10 +173,16 @@ void ArchipelagoClient::SynchSentLocations() { void ArchipelagoClient::SynchRecievedLocations() { // Open checks that have been found previously but went unsaved for(const int64_t apLoc : apClient->get_checked_locations()) { - // TODO call location checked function to open any unopened checks. + QueueExternalCheck(apLoc); } } +void ArchipelagoClient::QueueExternalCheck(const int64_t apLocation) { + const std::string checkName = apClient->get_location_name(apLocation, AP_Client_consts::AP_GAME_NAME); + const uint32_t RC = static_cast(Rando::StaticData::locationNameToEnum[checkName]); + GameInteractor_ExecuteOnRandomizerExternalCheck(RC); +} + bool ArchipelagoClient::IsConnected() { return apClient->get_state() == APClient::State::SLOT_CONNECTED; } diff --git a/soh/soh/Network/Archipelago/Archipelago.h b/soh/soh/Network/Archipelago/Archipelago.h index e077125e7c..9b517f6a24 100644 --- a/soh/soh/Network/Archipelago/Archipelago.h +++ b/soh/soh/Network/Archipelago/Archipelago.h @@ -49,6 +49,7 @@ class ArchipelagoClient{ void OnItemReceived(const ApItem apItem); void QueueItem(const ApItem item); + void QueueExternalCheck(int64_t apLocation); void SendGameWon(); From dbf8503369d683d2fb9ed4b86cc942ccd40bc176 Mon Sep 17 00:00:00 2001 From: Jerom Venneker Date: Mon, 26 May 2025 22:07:58 +0200 Subject: [PATCH 3/3] Added text recieved from AP to the log --- soh/soh/Enhancements/randomizer/context.cpp | 4 +-- soh/soh/Network/Archipelago/Archipelago.cpp | 35 ++++++++++--------- .../Archipelago/ArchipelagoConsoleWindow.cpp | 17 ++++----- .../Archipelago/ArchipelagoConsoleWindow.h | 2 +- .../Archipelago/ArchipelagoSettingsWindow.cpp | 2 +- 5 files changed, 32 insertions(+), 28 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp index 67502ff5ed..c9cc8e746a 100644 --- a/soh/soh/Enhancements/randomizer/context.cpp +++ b/soh/soh/Enhancements/randomizer/context.cpp @@ -349,11 +349,11 @@ void Context::SetSpoilerLoaded(const bool spoilerLoaded) { void Context::AddRecievedArchipelagoItem(const RandomizerGet item) { mAPrecieveQueue.emplace(item); std::string logMessage = "[LOG] Item Pushed: " + item; - ArchipelagoConsole_SendMessage(logMessage.c_str()); + ArchipelagoConsole_SendMessage(logMessage.c_str(), true); } GetItemEntry Context::GetArchipelagoGIEntry() { - ArchipelagoConsole_SendMessage("[LOG] Trying to get Item Entry"); + ArchipelagoConsole_SendMessage("[LOG] Trying to get Item Entry", true); if(mAPrecieveQueue.empty()) { // something must have gone wrong here, just give a rupee return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, GI_HEART); diff --git a/soh/soh/Network/Archipelago/Archipelago.cpp b/soh/soh/Network/Archipelago/Archipelago.cpp index e4c80b7a9a..775944fe33 100644 --- a/soh/soh/Network/Archipelago/Archipelago.cpp +++ b/soh/soh/Network/Archipelago/Archipelago.cpp @@ -25,18 +25,14 @@ extern PlayState* gPlayState; } ArchipelagoClient::ArchipelagoClient() { - std::string uuid = ap_get_uuid("uuid"); + uuid = ap_get_uuid("uuid"); gameWon = false; - - namespace apc = AP_Client_consts; - CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0); - bool itemQueued = false; + itemQueued = false; // call poll every frame COND_HOOK(GameInteractor::OnGameFrameUpdate, true, [](){ArchipelagoClient::GetInstance().Poll();}); COND_HOOK(GameInteractor::OnLoadGame, true, [](int32_t file_id){ArchipelagoClient::GetInstance().GameLoaded();}); - } ArchipelagoClient& ArchipelagoClient::GetInstance() { @@ -62,7 +58,7 @@ bool ArchipelagoClient::StartClient() { }); apClient->set_slot_connected_handler([&](const nlohmann::json data) { - ArchipelagoConsole_SendMessage("[LOG] Connected.", false); + ArchipelagoConsole_SendMessage("[LOG] Connected.", true); ArchipelagoClient::StartLocationScouts(); slotData = data; @@ -105,10 +101,10 @@ bool ArchipelagoClient::StartClient() { const std::string playerName = apItem.playerName; const std::string locationName = apItem.locationName; std::string logMessage = "[LOG] Location scouted: " + itemName + " for " + playerName + " in location " + locationName; - ArchipelagoConsole_SendMessage(logMessage.c_str()); + ArchipelagoConsole_SendMessage(logMessage.c_str(), true); } - ArchipelagoConsole_SendMessage("[LOG] Scouting finished."); + ArchipelagoConsole_SendMessage("[LOG] Scouting finished.", true); }); // 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) { @@ -117,6 +113,11 @@ bool ArchipelagoClient::StartClient() { } }); + apClient->set_print_json_handler([&](const std::list& nodes) { + std::string text = apClient->render_json(nodes, APClient::RenderFormat::TEXT); + ArchipelagoConsole_SendMessage(text.c_str(), false); + }); + return true; } @@ -131,7 +132,7 @@ void ArchipelagoClient::GameLoaded() { return; } - ArchipelagoConsole_SendMessage("[LOG] Synching Items and Locations."); + ArchipelagoConsole_SendMessage("[LOG] Synching Items and Locations.", true); SynchItems(); SynchSentLocations(); @@ -153,7 +154,7 @@ void ArchipelagoClient::StartLocationScouts() { void ArchipelagoClient::SynchItems() { // Send a Synch request to get any items we may have missed - ArchipelagoConsole_SendMessage("[LOG] Sending synch request"); + ArchipelagoConsole_SendMessage("[LOG] Sending synch request", true); apClient->Sync(); } @@ -168,7 +169,7 @@ void ArchipelagoClient::SynchSentLocations() { } } std::string locationLog = "[LOG] Synching " + std::to_string(checkedLocations.size())+ " checks already found in game"; - ArchipelagoConsole_SendMessage(locationLog.c_str()); + ArchipelagoConsole_SendMessage(locationLog.c_str(), true); apClient->LocationChecks(checkedLocations); } @@ -198,7 +199,7 @@ void ArchipelagoClient::CheckLocation(RandomizerCheck sohCheckId) { int64_t apItemId = apClient->get_location_id(std::string(apName)); std::string logMessage = "[LOG] Checked: " + apName + "(" + std::to_string(apItemId) + "), sending to AP server"; - ArchipelagoConsole_SendMessage(logMessage.c_str()); + ArchipelagoConsole_SendMessage(logMessage.c_str(), true); if(!IsConnected()) { return; @@ -214,7 +215,7 @@ void ArchipelagoClient::OnItemReceived(const ApItem apItem) { } std::string logMessage = "[Log] Recieved " + apItem.itemName; - ArchipelagoConsole_SendMessage(logMessage.c_str()); + ArchipelagoConsole_SendMessage(logMessage.c_str(), true); // add item to the queue recieveQueue.push(apItem); @@ -224,12 +225,12 @@ void ArchipelagoClient::QueueItem(const ApItem item) { if(item.index < gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex) { // Skip queueing any items we already have std::string logMessage = "[Log] Skipping giving " + item.itemName + ". We recieved this previously."; - ArchipelagoConsole_SendMessage(logMessage.c_str()); + ArchipelagoConsole_SendMessage(logMessage.c_str(), true); return; } std::string logMessage = "[Log] Giving " + item.itemName; - ArchipelagoConsole_SendMessage(logMessage.c_str()); + ArchipelagoConsole_SendMessage(logMessage.c_str(), true); const RandomizerGet RG = Rando::StaticData::itemNameToEnum[item.itemName]; if(RG == RG_NONE) { return; @@ -390,6 +391,8 @@ void InitArchipelagoData(bool isDebug) { } void RegisterArchipelago() { + CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0); + COND_HOOK(GameInteractor::OnRandomizerItemGivenHooks, IS_ARCHIPELAGO, [](uint32_t rc, GetItemEntry gi, uint8_t isGiSkipped) { if (rc == RC_ARCHIPELAGO_RECIEVED_ITEM) { diff --git a/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.cpp b/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.cpp index 75e359839f..af5bf1ce82 100644 --- a/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.cpp +++ b/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.cpp @@ -10,15 +10,16 @@ bool autoScroll = true; using namespace UIWidgets; 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)); + if (debugMessage && CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("DebugEnabled"), 0) == 0) { + return; } + 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() { diff --git a/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.h b/soh/soh/Network/Archipelago/ArchipelagoConsoleWindow.h index 9856969df9..46cc3332e2 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, bool debugMessage = true, ...); +void ArchipelagoConsole_SendMessage(const char* fmt, bool debugMessage = false, ...); #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 7f0d92a71c..162045a980 100644 --- a/soh/soh/Network/Archipelago/ArchipelagoSettingsWindow.cpp +++ b/soh/soh/Network/Archipelago/ArchipelagoSettingsWindow.cpp @@ -39,7 +39,7 @@ 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...", false); + ArchipelagoConsole_SendMessage("[LOG] Trying to connect...", true); } ImGui::SameLine();