Added some basic Item recieving from server, not thoroughly tested yet

This commit is contained in:
Jerom Venneker
2025-02-10 20:58:38 +01:00
parent 51be461254
commit ea2e718c06
10 changed files with 145 additions and 20 deletions

2
APCpp

Submodule APCpp updated: c671d93553...38d5cf0798

View File

@@ -8,6 +8,8 @@
#include <iostream>
#include "fixed_string.hpp"
#include "randomizerTypes.h"
#include "static_data.h"
//extern "C" {
// #include "include/z64item.h"
@@ -33,6 +35,8 @@ auto SubscribeToSlotData() {
}
ArchipelagoClient::ArchipelagoClient() {
ItemRecievedCallback = nullptr;
namespace apc = AP_Client_consts;
CVarSetInteger("archipelago_connected", 0);
strncpy(server_address, CVarGetString(apc::SETTING_ADDRESS, apc::DEFAULT_SERVER_NAME), apc::MAX_ADDRESS_LENGTH);
@@ -183,6 +187,30 @@ void ArchipelagoClient::save_data() {
CVarSetString(AP_Client_consts::SETTING_NAME, slot_name);
}
bool ArchipelagoClient::isConnected() {
return AP_GetConnectionStatus() == AP_ConnectionStatus::Authenticated;
}
void ArchipelagoClient::check_location(RandomizerCheck SoH_check_id) {
std::string_view ap_name = Rando::StaticData::SohCheckToAP[SoH_check_id];
int64_t ap_item_id = CheckNameToId(std::string(ap_name));
SPDLOG_TRACE("Checked: {}({}), sending to AP server", ap_name, ap_item_id);
// currently not sending, because i only get so many real chances
if(!isConnected()) {
return;
}
AP_SendItem(ap_item_id);
}
void ArchipelagoClient::addItemRecievedCallback(std::function<void(const std::string&)> callback) {
ItemRecievedCallback = callback;
}
void ArchipelagoClient::removeItemRecievedCallback(std::function<void(const std::string&)> old_callback) {
ItemRecievedCallback = nullptr;
}
void ArchipelagoClient::on_connected() {
// todo implement me
SPDLOG_TRACE("AP Connected!!");
@@ -197,7 +225,14 @@ void ArchipelagoClient::on_clear_items() {
}
void ArchipelagoClient::on_item_recieved(int64_t recieved_item_id, bool notify_player) {
// todo implement me
// call each callback
SPDLOG_TRACE("Trying to give rupie...");
std::string item_name = getAPitemName(recieved_item_id);
ArchipelagoClient& ap_client = ArchipelagoClient::getInstance();
if(ap_client.ItemRecievedCallback) {
SPDLOG_TRACE("Giving Rupie! {}", item_name);
ap_client.ItemRecievedCallback.operator()(item_name); // somehow passing it through the itemname breaks it????
}
}
void ArchipelagoClient::on_location_checked(int64_t location_id) {
@@ -237,21 +272,23 @@ void ArchipelagoWindow::ArchipelagoDrawConnectPage() {
ImGui::InputText("Slot Name", AP_client.get_slot_name_buff(), AP_Client_consts::MAX_PLAYER_NAME_LENGHT);
ImGui::InputText("Password (leave blank for no password)", AP_client.get_password_buff(), AP_Client_consts::MAX_PASSWORD_LENGTH, ImGuiInputTextFlags_Password);
char connected_text[25] = "Disconnected";
static char connected_text[25] = "Disconnected";
if(ImGui::Button("Connect")) {
bool success = AP_client.start_client();
if(success) {
strncpy(connected_text, "Connected!", 25);
SPDLOG_TRACE("Connected!!");
}
else {
strncpy(connected_text, "Connection failed!", 25);
SPDLOG_TRACE("Connection failed :(");
}
}
ImGui::SameLine();
ImGui::Text(connected_text);
AP_ConnectionStatus con_status = AP_GetConnectionStatus();
if(con_status == AP_ConnectionStatus::Connected) {
strncpy(connected_text, "Connected!", 25);
} else if(con_status == AP_ConnectionStatus::Authenticated) {
strncpy(connected_text, "Authenticated!", 25);
}
else {
strncpy(connected_text, "Not Connected", 25);
}
if(ImGui::Button("scout")) {
AP_client.start_location_scouts();
}
@@ -265,4 +302,8 @@ void ArchipelagoWindow::ArchipelagoDrawConnectPage() {
void ArchipelagoWindow::DrawElement() {
ArchipelagoDrawConnectPage();
UIWidgets::PaddedSeparator();
if(ImGui::Button("give blue ruppie")) {
ArchipelagoClient::getInstance().on_item_recieved(66077, true);
}
};

View File

@@ -3,6 +3,11 @@
#include "fixed_string.hpp"
#include "randomizerTypes.h"
#include "static_data.h"
#include <vector>
namespace AP_Client_consts {
static constexpr int MAX_ADDRESS_LENGTH = 64;
static constexpr int MAX_PLAYER_NAME_LENGHT = 17;
@@ -30,6 +35,19 @@ class ArchipelagoClient {
const std::vector<AP_NetworkItem>& get_scouted_items();
void add_slot_data(std::string_view key, int id);
//void add_slot_data(std::string_view key, int id);
bool isConnected();
void check_location(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
static void on_item_recieved(int64_t recieved_item_id, bool notify_player);
protected:
ArchipelagoClient();
@@ -56,12 +74,13 @@ class ArchipelagoClient {
static void on_connected();
static void on_couldntConnect(AP_ConnectionStatus connection_status);
static void on_clear_items();
static void on_item_recieved(int64_t recieved_item_id, bool notify_player);
static void on_location_checked(int64_t location_id);
static void on_deathlink_recieved() { }; // TODO: implement me
static void on_location_scouted(std::vector<AP_NetworkItem> network_items);
// callbacks
std::function<void(const std::string&)> ItemRecievedCallback;
};

View File

@@ -271,6 +271,30 @@ void Context::SetSpoilerLoaded(const bool spoilerLoaded) {
mSpoilerLoaded = spoilerLoaded;
}
void Context::AddRecievedArchipelagoItem(const std::string& ap_item_id) {
mAPrecieveQueue.emplace(ap_item_id);
SPDLOG_TRACE("Item Pushed {}", ap_item_id);
}
GetItemEntry Context::GetArchipelagoGIEntry() {
SPDLOG_TRACE("Trying to get Item Entry");
if(mAPrecieveQueue.empty()) {
// something must have gone wrong here, just give a rupee
return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, GI_HEART);
}
// get the first item from the archipelago queue
std::string_view recieved_ap_item = mAPrecieveQueue.front();
RandomizerGet item_id = StaticData::APitemToSoh[recieved_ap_item];
assert(item_id != RG_NONE);
Item& item = StaticData::RetrieveItem(item_id);
SPDLOG_TRACE("Found item! {}, {}", recieved_ap_item, (int)item_id);
GetItemEntry item_entry = item.GetGIEntry_Copy();
mAPrecieveQueue.pop();
return item_entry; // todo: add custom text maybe?
}
GetItemEntry Context::GetFinalGIEntry(const RandomizerCheck rc, const bool checkObtainability, const GetItemID ogItemId) {
const auto itemLoc = GetItemLocation(rc);
if (itemLoc->GetPlacedRandomizerGet() == RG_NONE) {
@@ -392,8 +416,9 @@ void Context::ParseArchipelagoItemsLocations(std::vector<AP_NetworkItem> scouted
itemLocationTable[rc].SetPlacedItem(item);
} else {
// other player item
itemLocationTable[rc].SetPlacedItem(RG_RECOVERY_HEART); // Ap item doesn't work yet
//overrides[rc] = ItemOverride(rc, RG_ZELDAS_LETTER);
itemLocationTable[rc].SetPlacedItem(RG_ARCHIPELAGO_ITEM);
// i'll have to figure out custom names at some point, this currently does nothing
//overrides[rc] = ItemOverride(rc, RG_DEKU_NUTS_5);
//std::string getText = ap_item.playerName + "'s " + ap_item.itemName;
//overrides[rc].SetTrickName(Text(getText, getText, getText));
}

View File

@@ -107,6 +107,8 @@ class Context {
*/
RandoOptionLACSCondition LACSCondition() const;
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
void AddRecievedArchipelagoItem(const std::string& ap_item_id);
GetItemEntry GetArchipelagoGIEntry();
void ParseSpoiler(const char* spoilerFileName);
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
void ParseItemLocationsJson(nlohmann::json spoilerFileJson);
@@ -186,5 +188,6 @@ class Context {
std::string mHash;
std::string mSeedString;
uint32_t mFinalSeed = 0;
std::queue<std::string> mAPrecieveQueue = {};
};
} // namespace Rando

View File

@@ -16,6 +16,7 @@
#include "soh/Notification/Notification.h"
#include "soh/SaveManager.h"
#include "soh/Enhancements/randomizer/ShuffleFairies.h"
#include "archipelago.h"
extern "C" {
#include "macros.h"
@@ -215,6 +216,12 @@ static std::queue<RandomizerCheck> randomizerQueuedChecks;
static RandomizerCheck randomizerQueuedCheck = RC_UNKNOWN_CHECK;
static GetItemEntry randomizerQueuedItemEntry = GET_ITEM_NONE;
void ArchipelagoOnRecieveItem(const std::string& ap_item_id) {
SPDLOG_TRACE("Recieve item handler called! {}", ap_item_id);
randomizerQueuedChecks.push(RC_ARCHIPELAGO_RECIEVED_ITEM);
Rando::Context::GetInstance()->AddRecievedArchipelagoItem(ap_item_id);
}
void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) {
// Consume adult trade items
if (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) && flagType == FLAG_RANDOMIZER_INF) {
@@ -271,11 +278,17 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() {
return;
}
GetItemEntry getItemEntry;
RandomizerCheck rc = randomizerQueuedChecks.front();
auto loc = Rando::Context::GetInstance()->GetItemLocation(rc);
RandomizerGet vanillaRandomizerGet = Rando::StaticData::GetLocation(rc)->GetVanillaItem();
GetItemID vanillaItem = (GetItemID)Rando::StaticData::RetrieveItem(vanillaRandomizerGet).GetItemID();
GetItemEntry getItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)vanillaRandomizerGet);
if(rc == RC_ARCHIPELAGO_RECIEVED_ITEM) {
getItemEntry = Rando::Context::GetInstance()->GetArchipelagoGIEntry();
} else {
RandomizerGet vanillaRandomizerGet = Rando::StaticData::GetLocation(rc)->GetVanillaItem();
GetItemID vanillaItem = (GetItemID)Rando::StaticData::RetrieveItem(vanillaRandomizerGet).GetItemID();
getItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)vanillaRandomizerGet);
}
SPDLOG_TRACE("RC found!");
if (loc->HasObtained()) {
SPDLOG_INFO("RC {} already obtained, skipping", static_cast<uint32_t>(rc));
@@ -331,9 +344,19 @@ void RandomizerOnPlayerUpdateForItemQueueHandler() {
void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) {
if (randomizerQueuedCheck == RC_UNKNOWN_CHECK) return;
SPDLOG_TRACE("Dropped into recieve handler!");
auto loc = Rando::Context::GetInstance()->GetItemLocation(randomizerQueuedCheck);
if (randomizerQueuedItemEntry.modIndex == receivedItemEntry.modIndex && randomizerQueuedItemEntry.itemId == receivedItemEntry.itemId) {
SPDLOG_INFO("Item received mod {} item {} from RC {}", receivedItemEntry.modIndex, receivedItemEntry.itemId, static_cast<uint32_t>(randomizerQueuedCheck));
// todo maybe move to seperate function
// let arhipelago know we got this check
if(randomizerQueuedCheck != RC_ARCHIPELAGO_RECIEVED_ITEM) {
ArchipelagoClient& ap_client = ArchipelagoClient::getInstance();
ap_client.check_location(randomizerQueuedCheck);
}
loc->SetCheckStatus(RCSHOW_COLLECTED);
CheckTracker::SpoilAreaFromCheck(randomizerQueuedCheck);
CheckTracker::RecalculateAllAreaTotals();
@@ -2406,6 +2429,8 @@ void RandomizerRegisterHooks() {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(shuffleFreestandingOnVanillaBehaviorHook);
ArchipelagoClient::getInstance().removeItemRecievedCallback(ArchipelagoOnRecieveItem);
onFlagSetHook = 0;
onSceneFlagSetHook = 0;
onPlayerUpdateForRCQueueHook = 0;
@@ -2486,5 +2511,7 @@ void RandomizerRegisterHooks() {
if (RAND_GET_OPTION(RSK_SHUFFLE_FAIRIES)) {
ShuffleFairies_RegisterHooks();
}
ArchipelagoClient::getInstance().addItemRecievedCallback(ArchipelagoOnRecieveItem);
});
}

View File

@@ -393,7 +393,7 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce-Fragment" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
// Archipelago
itemTable[RG_ARCHIPELAGO_ITEM] = /* doesn't work :P*/ Item(RG_ARCHIPELAGO_ITEM, Text{"AP Item", "AP Item", "AP_Item"}, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_NONE, RG_ARCHIPELAGO_ITEM, OBJECT_GI_LETTER, GID_LETTER_ZELDA, TEXT_RANDOMIZER_CUSTOM_ITEM, 0, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_ARCHIPELAGO_ITEM] = Item(RG_ARCHIPELAGO_ITEM, Text{"AP Item", "AP Item", "AP Item"}, ITEMTYPE_EVENT, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_NONE, RG_ARCHIPELAGO_ITEM, OBJECT_GI_LETTER, GID_LETTER_ZELDA, TEXT_RANDOMIZER_CUSTOM_ITEM, 0, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_RANDOMIZER);
// Init itemNameToEnum
for (auto& item : itemTable) {

View File

@@ -130,6 +130,8 @@ bool ItemLocation::HasObtained() const {
}
void ItemLocation::SetCheckStatus(RandomizerCheckStatus status_) {
if(rc == RC_ARCHIPELAGO_RECIEVED_ITEM) // never count the AP recieve trigger as 'collected'
return;
status = status_;
}

View File

@@ -3332,7 +3332,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) {
void Randomizer::CreateCustomMessages() {
// RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED
// with GIMESSAGE(getItemID, itemID, english, german, french).
const std::array<GetItemMessage, 112> getItemMessages = {{
const std::array<GetItemMessage, 113> getItemMessages = {{
GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON,
"You found %gGreg%w!",
"%gGreg%w! Du hast ihn wirklich gefunden!",
@@ -3767,6 +3767,7 @@ void Randomizer::CreateCustomMessages() {
GIMESSAGE_NO_GERMAN(RG_DEKU_NUT_BAG, ITEM_NUT,
"You found the %rDeku Nut Bag%w!&You can now hold deku nuts!",
"Vous avez trouvé le %rSac de Noix Mojo%w!&Vous pouvez maintenant porter des Noix Mojo!"),
GIMESSAGE_NO_GERMAN(RG_ARCHIPELAGO_ITEM, ITEM_BEAN, "You found an %rAP_ITEM%w", "Je m'apelle not %rNot Translated%w"),
}};
CreateGetItemMessages(&getItemMessages);
CreateRupeeMessages();
@@ -3881,6 +3882,11 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
return Return_Item_Entry(giEntry, RG_NONE);
}
//if it's an archipelago item, don't give anything
if(item == RG_ARCHIPELAGO_ITEM) {
return Return_Item_Entry(giEntry, RG_NONE);
}
//bottle items
if (item >= RG_BOTTLE_WITH_RED_POTION && item <= RG_BOTTLE_WITH_BIG_POE) {
for (u16 i = 0; i < 4; i++) {

View File

@@ -13,7 +13,8 @@
// which doesn't exist yet.
typedef enum {
MOD_NONE,
MOD_RANDOMIZER
MOD_RANDOMIZER,
MOD_ARCHIPELAGO // no actually used yet i think
} ModIndex;
typedef enum {
TABLE_VANILLA = MOD_NONE,
@@ -2848,6 +2849,7 @@ typedef enum {
RC_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY,
RC_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY,
RC_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY,
RC_ARCHIPELAGO_RECIEVED_ITEM,
RC_MAX
} RandomizerCheck;