Rework Item Queue, Repeated connections should no longer give multiple copies of the same item

This commit is contained in:
Jerom Venneker
2025-05-25 21:17:44 +02:00
parent ea95ca0a9a
commit 603c163167
3 changed files with 52 additions and 12 deletions

View File

@@ -30,6 +30,7 @@ ArchipelagoClient::ArchipelagoClient() {
namespace apc = AP_Client_consts; namespace apc = AP_Client_consts;
CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0); CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0);
bool itemQueued = false;
// call poll every frame // call poll every frame
COND_HOOK(GameInteractor::OnGameFrameUpdate, true, [](){ArchipelagoClient::GetInstance().Poll();}); COND_HOOK(GameInteractor::OnGameFrameUpdate, true, [](){ArchipelagoClient::GetInstance().Poll();});
@@ -73,7 +74,14 @@ bool ArchipelagoClient::StartClient() {
apClient->set_items_received_handler([&](const std::list<APClient::NetworkItem>& items) { apClient->set_items_received_handler([&](const std::list<APClient::NetworkItem>& items) {
for(const APClient::NetworkItem& item : 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 }); apClient->LocationChecks({ apItemId });
} }
void ArchipelagoClient::OnItemReceived(int64_t apItemId, int64_t itemIndex) { void ArchipelagoClient::OnItemReceived(const ApItem apItem) {
if(!GameInteractor::IsSaveLoaded(true)) { if(!GameInteractor::IsSaveLoaded(true)) {
// Don't queue up any items when we aren't in game // 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 // Any Items missed this way will get synched when we load the save
return; return;
} }
if(itemIndex < gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex) { std::string logMessage = "[Log] Recieved " + apItem.itemName;
// Skip recieving any items we already have 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; return;
} }
const std::string item_name = apClient->get_item_name(apItemId, AP_Client_consts::AP_GAME_NAME); std::string logMessage = "[Log] Giving " + item.itemName;
std::string logMessage = "[Log] Recieved " + item_name;
ArchipelagoConsole_SendMessage(logMessage.c_str()); ArchipelagoConsole_SendMessage(logMessage.c_str());
const RandomizerGet item = Rando::StaticData::itemNameToEnum[item_name]; const RandomizerGet RG = Rando::StaticData::itemNameToEnum[item.itemName];
GameInteractor_ExecuteOnArchipelagoItemRecieved(static_cast<int32_t>(item)); if(RG == RG_NONE) {
return;
}
itemQueued = true;
GameInteractor_ExecuteOnArchipelagoItemRecieved(static_cast<int32_t>(RG));
} }
void ArchipelagoClient::SendGameWon() { void ArchipelagoClient::SendGameWon() {
@@ -218,6 +240,14 @@ void ArchipelagoClient::Poll() {
return; return;
} }
// queue another item to be recieved
if(!itemQueued && recieveQueue.size() > 0) {
const ApItem item = recieveQueue.front();
recieveQueue.pop();
QueueItem(item);
}
apClient->poll(); apClient->poll();
} }
@@ -369,6 +399,7 @@ void RegisterArchipelago() {
[](uint32_t rc) { [](uint32_t rc) {
if (rc == RC_ARCHIPELAGO_RECIEVED_ITEM) { if (rc == RC_ARCHIPELAGO_RECIEVED_ITEM) {
gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex++; gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex++;
ArchipelagoClient::GetInstance().itemQueued = false;
} else { } else {
ArchipelagoClient::GetInstance().CheckLocation((RandomizerCheck)rc); ArchipelagoClient::GetInstance().CheckLocation((RandomizerCheck)rc);
} }

View File

@@ -3,6 +3,7 @@
#include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/Enhancements/randomizer/randomizerTypes.h"
#include "soh/Enhancements/randomizer/static_data.h" #include "soh/Enhancements/randomizer/static_data.h"
#include <vector> #include <vector>
#include <queue>
// Forward declaration // Forward declaration
class APClient; class APClient;
@@ -22,7 +23,7 @@ class ArchipelagoClient{
std::string locationName; std::string locationName;
std::string playerName; std::string playerName;
unsigned int flags; unsigned int flags;
int index; uint64_t index;
}; };
static ArchipelagoClient& GetInstance(); static ArchipelagoClient& GetInstance();
@@ -46,14 +47,15 @@ class ArchipelagoClient{
bool IsConnected(); bool IsConnected();
void CheckLocation(RandomizerCheck SoH_check_id); void CheckLocation(RandomizerCheck SoH_check_id);
// todo move me back down when done testing void OnItemReceived(const ApItem apItem);
void OnItemReceived(int64_t apItemId, int64_t itemIndex); void QueueItem(const ApItem item);
void SendGameWon(); void SendGameWon();
void Poll(); void Poll();
std::unique_ptr<APClient> apClient; std::unique_ptr<APClient> apClient;
bool itemQueued;
protected: protected:
ArchipelagoClient(); ArchipelagoClient();
@@ -71,6 +73,7 @@ class ArchipelagoClient{
std::map<std::string, int> slotData; std::map<std::string, int> slotData;
std::set<int64_t> locations; std::set<int64_t> locations;
std::vector<ApItem> scoutedItems; std::vector<ApItem> scoutedItems;
std::queue<ApItem> recieveQueue;
}; };
void LoadArchipelagoData(); void LoadArchipelagoData();

View File

@@ -63,7 +63,13 @@ void ArchipelagoSettingsWindow::DrawElement() {
ImGui::SameLine(); ImGui::SameLine();
if (UIWidgets::Button("Give Blue Rupee", if (UIWidgets::Button("Give Blue Rupee",
UIWidgets::ButtonOptions().Color(THEME_COLOR).Size(ImVec2(0.0, 0.0)))) { 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);
} }
} }
}; };