Added Item Synch on game load

This commit is contained in:
Jerom Venneker
2025-05-23 18:04:08 +02:00
parent c15abdc411
commit b2c2be034e
2 changed files with 60 additions and 27 deletions

View File

@@ -6,10 +6,12 @@
#include <fstream> #include <fstream>
#include <filesystem> #include <filesystem>
#include <iostream> #include <iostream>
#include <string>
#include "soh/Network/Archipelago/ArchipelagoConsoleWindow.h" #include "soh/Network/Archipelago/ArchipelagoConsoleWindow.h"
#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 "soh/Enhancements/randomizer/context.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp" #include "soh/ShipInit.hpp"
@@ -24,14 +26,15 @@ extern PlayState* gPlayState;
ArchipelagoClient::ArchipelagoClient() { ArchipelagoClient::ArchipelagoClient() {
std::string uuid = ap_get_uuid("uuid"); std::string uuid = ap_get_uuid("uuid");
ItemRecievedCallback = nullptr;
gameWon = false; gameWon = false;
namespace apc = AP_Client_consts; namespace apc = AP_Client_consts;
CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0); CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0);
// call poll every frame // call poll every frame
COND_HOOK(GameInteractor::OnGameFrameUpdate, true, [](){ArchipelagoClient::GetInstance().Poll();}) COND_HOOK(GameInteractor::OnGameFrameUpdate, true, [](){ArchipelagoClient::GetInstance().Poll();});
COND_HOOK(GameInteractor::OnLoadGame, true, [](int32_t file_id){ArchipelagoClient::GetInstance().GameLoaded();});
} }
ArchipelagoClient& ArchipelagoClient::GetInstance() { ArchipelagoClient& ArchipelagoClient::GetInstance() {
@@ -63,7 +66,7 @@ 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, false); // todo get rid of notify, since it doesn't work for us right now anyway OnItemReceived(item.item, item.index);
} }
}); });
@@ -97,6 +100,15 @@ bool ArchipelagoClient::StartClient() {
return true; return true;
} }
void ArchipelagoClient::GameLoaded() {
if(!IS_ARCHIPELAGO) {
// apClient->reset();
// return;
}
SynchItems();
}
void ArchipelagoClient::StartLocationScouts() { void ArchipelagoClient::StartLocationScouts() {
std::set<int64_t> missing_loc_set = apClient->get_missing_locations(); std::set<int64_t> missing_loc_set = apClient->get_missing_locations();
std::set<int64_t> found_loc_set = apClient->get_checked_locations(); std::set<int64_t> found_loc_set = apClient->get_checked_locations();
@@ -110,6 +122,32 @@ void ArchipelagoClient::StartLocationScouts() {
apClient->LocationScouts(location_list); apClient->LocationScouts(location_list);
} }
void ArchipelagoClient::SynchItems() {
ArchipelagoConsole_SendMessage("[LOG] Synching Items and Locations.");
// send already checked locations
std::list<int64_t> checkedLocations;
for(const auto& loc : Rando::StaticData::GetLocationTable()) {
const RandomizerCheck rc = loc.GetRandomizerCheck();
if(Rando::Context::GetInstance()->GetItemLocation(rc)->HasObtained()) {
const int64_t apLocation = apClient->get_location_id(loc.GetName());
checkedLocations.emplace_back(apLocation);
}
}
std::string locationLog = "[LOG] Synching " + std::to_string(checkedLocations.size())+ " checks already found in game";
ArchipelagoConsole_SendMessage(locationLog.c_str());
apClient->LocationChecks(checkedLocations);
// 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.
}
// Send a Synch request to get any items we may have missed
ArchipelagoConsole_SendMessage("[LOG] Sending synch request");
apClient->Sync();
}
bool ArchipelagoClient::IsConnected() { bool ArchipelagoClient::IsConnected() {
return apClient->get_state() == APClient::State::SLOT_CONNECTED; return apClient->get_state() == APClient::State::SLOT_CONNECTED;
} }
@@ -130,16 +168,21 @@ void ArchipelagoClient::CheckLocation(RandomizerCheck sohCheckId) {
apClient->LocationChecks({ apItemId }); apClient->LocationChecks({ apItemId });
} }
void ArchipelagoClient::AddItemRecievedCallback(std::function<void(const std::string&)> callback) { void ArchipelagoClient::OnItemReceived(int64_t apItemId, int64_t itemIndex) {
ItemRecievedCallback = callback; 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;
}
void ArchipelagoClient::RemoveItemRecievedCallback(std::function<void(const std::string&)> old_callback) { if(itemIndex < gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex) {
ItemRecievedCallback = nullptr; // Skip recieving any items we already have
} return;
}
void ArchipelagoClient::OnItemReceived(int64_t recieved_item_id, bool notify_player) { const std::string item_name = apClient->get_item_name(apItemId, AP_Client_consts::AP_GAME_NAME);
const std::string item_name = apClient->get_item_name(recieved_item_id, AP_Client_consts::AP_GAME_NAME); std::string logMessage = "[Log] Recieved " + item_name;
ArchipelagoConsole_SendMessage(logMessage.c_str());
const RandomizerGet item = Rando::StaticData::itemNameToEnum[item_name]; const RandomizerGet item = Rando::StaticData::itemNameToEnum[item_name];
GameInteractor_ExecuteOnArchipelagoItemRecieved(static_cast<int32_t>(item)); GameInteractor_ExecuteOnArchipelagoItemRecieved(static_cast<int32_t>(item));
} }
@@ -159,7 +202,7 @@ void ArchipelagoClient::Poll() {
apClient->poll(); apClient->poll();
} }
const std::string& ArchipelagoClient::GetSlotName() const { const std::string ArchipelagoClient::GetSlotName() const {
if(apClient == NULL) { if(apClient == NULL) {
return ""; return "";
} }
@@ -310,7 +353,7 @@ void RegisterArchipelago() {
COND_HOOK(GameInteractor::OnRandomizerItemGivenHooks, IS_ARCHIPELAGO, COND_HOOK(GameInteractor::OnRandomizerItemGivenHooks, IS_ARCHIPELAGO,
[](uint32_t rc) { [](uint32_t rc) {
if (rc == RC_ARCHIPELAGO_RECIEVED_ITEM) { if (rc == RC_ARCHIPELAGO_RECIEVED_ITEM) {
// Update lastReceivedIndex gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex++;
} else { } else {
ArchipelagoClient::GetInstance().CheckLocation((RandomizerCheck)rc); ArchipelagoClient::GetInstance().CheckLocation((RandomizerCheck)rc);
} }

View File

@@ -30,10 +30,12 @@ class ArchipelagoClient{
bool StartClient(); bool StartClient();
bool StopClient(); bool StopClient();
void GameLoaded();
void StartLocationScouts(); void StartLocationScouts();
void SynchItems();
// getters // getters
const std::string& GetSlotName() const; const std::string GetSlotName() const;
const char* GetConnectionStatus(); const char* GetConnectionStatus();
const std::map<std::string, int>& GetSlotData(); const std::map<std::string, int>& GetSlotData();
@@ -42,12 +44,8 @@ class ArchipelagoClient{
bool IsConnected(); bool IsConnected();
void CheckLocation(RandomizerCheck SoH_check_id); void CheckLocation(RandomizerCheck SoH_check_id);
// callback slots
void AddItemRecievedCallback(std::function<void(const std::string&)> callback);
void RemoveItemRecievedCallback(std::function<void(const std::string&)> old_callback);
// todo move me back down when done testing // todo move me back down when done testing
void OnItemReceived(int64_t recieved_item_id, bool notify_player); void OnItemReceived(int64_t apItemId, int64_t itemIndex);
void SendGameWon(); void SendGameWon();
@@ -71,14 +69,6 @@ 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;
// Callback Functions
void OnLocationChecked(int64_t location_id);
void OnDeathLinkReceived() { }; // TODO: implement me
// Callbacks
std::function<void(const std::string&)> ItemRecievedCallback;
}; };
void LoadArchipelagoData(); void LoadArchipelagoData();