Added connection status to archi file select

This commit is contained in:
Jerom Venneker
2025-07-15 19:07:19 +02:00
parent e272300245
commit 9fbf67fc94
10 changed files with 130 additions and 9 deletions

View File

@@ -178,6 +178,7 @@ typedef struct ShipArchipelagoSaveContextData {
u32 lastReceivedItemIndex; u32 lastReceivedItemIndex;
char roomHash[100]; char roomHash[100];
char slotName[17]; char slotName[17];
char archiUri[50];
ArchipelagoLocationData locations[RC_MAX]; ArchipelagoLocationData locations[RC_MAX];
} ShipArchipelagoSaveContextData; } ShipArchipelagoSaveContextData;

View File

@@ -111,6 +111,24 @@ std::array<std::string, LANGUAGE_MAX> ArchipelagoSettingsMenuText[ASM_MAX]{
"Todo", "Todo",
"Todo", "Todo",
}, },
//ASM_CHAR_START_TO_CONNECT
{
"Start to automatically connect to this slot",
"Todo",
"Todo",
},
//ASM_CHAR_SELECT_CONNECTED_TO_OTHER_SLOT
{
"Connected to a different slot",
"Todo",
"Todo",
},
// ASM_CHAR_SELECT_CHANGE_CONNECTION_INFO
{
"Z-Connection Settings",
"Z-Todo",
"Z-Todo",
}
}; };
const char* SohFileSelect_GetRandomizerSettingText(uint8_t optionIndex, uint8_t language) { const char* SohFileSelect_GetRandomizerSettingText(uint8_t optionIndex, uint8_t language) {

View File

@@ -30,6 +30,9 @@ typedef enum {
ASM_CONNECTING, ASM_CONNECTING,
ASM_CONNECTED, ASM_CONNECTED,
ASM_STATUS, ASM_STATUS,
ASM_CHAR_START_TO_CONNECT,
ASM_CHAR_SELECT_CONNECTED_TO_OTHER_SLOT,
ASM_CHAR_SELECT_CHANGE_CONNECTION_INFO,
ASM_MAX ASM_MAX
} ArchipelagoSettingsMenuEnums; } ArchipelagoSettingsMenuEnums;

View File

@@ -45,9 +45,10 @@ bool ArchipelagoClient::StartClient() {
disconnecting = false; disconnecting = false;
retries = 0; retries = 0;
uri = CVarGetString(CVAR_REMOTE_ARCHIPELAGO("ServerAddress"), "localhost:38281");
apClient = std::unique_ptr<APClient>( apClient = std::unique_ptr<APClient>(
new APClient(uuid, AP_Client_consts::AP_GAME_NAME, new APClient(uuid, AP_Client_consts::AP_GAME_NAME,
CVarGetString(CVAR_REMOTE_ARCHIPELAGO("ServerAddress"), "localhost:38281"), "cacert.pem")); uri, "cacert.pem"));
CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 1); // Connecting CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 1); // Connecting
@@ -424,6 +425,23 @@ void ArchipelagoClient::Poll() {
apClient->poll(); apClient->poll();
} }
bool ArchipelagoClient::slotMatch(const std::string& slotName, const std::string& roomHash) {
if (apClient == nullptr) {
return false;
}
if(disconnecting) {
return false;
}
const std::string seed = apClient->get_seed();
const std::string slot = GetSlotName();
const bool seedMatch = apClient->get_seed().compare(roomHash) == 0;
const bool slotMatch = GetSlotName().compare(slotName) == 0;
return seedMatch && slotMatch;
}
bool ArchipelagoClient::isRightSaveLoaded() const { bool ArchipelagoClient::isRightSaveLoaded() const {
const bool seedMatch = apClient->get_seed().compare(gSaveContext.ship.quest.data.archipelago.roomHash) == 0; const bool seedMatch = apClient->get_seed().compare(gSaveContext.ship.quest.data.archipelago.roomHash) == 0;
const bool slotMatch = GetSlotName().compare(gSaveContext.ship.quest.data.archipelago.slotName) == 0; const bool slotMatch = GetSlotName().compare(gSaveContext.ship.quest.data.archipelago.slotName) == 0;
@@ -524,6 +542,8 @@ extern "C" void Archipelago_InitSaveFile() {
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash)); ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash));
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.slotName, client.apClient->get_slot(), SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.slotName, client.apClient->get_slot(),
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName)); ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.archiUri, client.uri,
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.archiUri));
for (uint32_t i = 0; i < scoutedItems.size(); i++) { for (uint32_t i = 0; i < scoutedItems.size(); i++) {
RandomizerCheck rc = Rando::StaticData::locationNameToEnum[scoutedItems[i].locationName]; RandomizerCheck rc = Rando::StaticData::locationNameToEnum[scoutedItems[i].locationName];
@@ -546,6 +566,8 @@ void LoadArchipelagoData() {
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash)); ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash));
SaveManager::Instance->LoadCharArray("slotName", gSaveContext.ship.quest.data.archipelago.slotName, SaveManager::Instance->LoadCharArray("slotName", gSaveContext.ship.quest.data.archipelago.slotName,
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName)); ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
SaveManager::Instance->LoadCharArray("archiUri", gSaveContext.ship.quest.data.archipelago.archiUri,
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.archiUri));
SaveManager::Instance->LoadArray( SaveManager::Instance->LoadArray(
"locations", ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.locations), [](size_t i) { "locations", ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.locations), [](size_t i) {
@@ -567,6 +589,7 @@ void SaveArchipelagoData(SaveContext* saveContext, int sectionID, bool fullSave)
SaveManager::Instance->SaveData("roomHash", saveContext->ship.quest.data.archipelago.roomHash); SaveManager::Instance->SaveData("roomHash", saveContext->ship.quest.data.archipelago.roomHash);
SaveManager::Instance->SaveData("slotName", saveContext->ship.quest.data.archipelago.slotName); SaveManager::Instance->SaveData("slotName", saveContext->ship.quest.data.archipelago.slotName);
SaveManager::Instance->SaveData("archiUri", saveContext->ship.quest.data.archipelago.archiUri);
SaveManager::Instance->SaveArray( SaveManager::Instance->SaveArray(
"locations", ARRAY_COUNT(saveContext->ship.quest.data.archipelago.locations), [&](size_t i) { "locations", ARRAY_COUNT(saveContext->ship.quest.data.archipelago.locations), [&](size_t i) {
@@ -587,6 +610,8 @@ void InitArchipelagoData(bool isDebug) {
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash)); ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash));
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.slotName, "", SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.slotName, "",
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName)); ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.archiUri, "",
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.archiUri));
for (uint32_t i = 0; i < ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.locations); i++) { for (uint32_t i = 0; i < ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.locations); i++) {
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.locations[i].itemName, "", SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.locations[i].itemName, "",

View File

@@ -62,11 +62,14 @@ class ArchipelagoClient {
void SendMessageToConsole(const std::string message); void SendMessageToConsole(const std::string message);
void Poll(); void Poll();
bool slotMatch(const std::string& slotName, const std::string& roomHash);
std::unique_ptr<APClient> apClient; std::unique_ptr<APClient> apClient;
bool itemQueued; bool itemQueued;
bool disconnecting; bool disconnecting;
bool isDeathLinkedDeath; bool isDeathLinkedDeath;
int retries; int retries;
std::string uri;
protected: protected:
ArchipelagoClient(); ArchipelagoClient();

View File

@@ -2728,6 +2728,12 @@ extern "C" void ParseArchipelago() {
OTRGlobals::Instance->gRandoContext->ParseArchipelago(); OTRGlobals::Instance->gRandoContext->ParseArchipelago();
} }
extern "C" bool checkArchipelagoSlotInfo(const char* slotName, const char* roomHash) {
const std::string slot = std::string(slotName);
const std::string room = std::string(roomHash);
return ArchipelagoClient::GetInstance().slotMatch(slot, room);
}
extern "C" void CheckTracker_RecalculateAvailableChecks() { extern "C" void CheckTracker_RecalculateAvailableChecks() {
CheckTracker::RecalculateAvailableChecks(); CheckTracker::RecalculateAvailableChecks();
} }

View File

@@ -173,6 +173,7 @@ void CheckTracker_RecalculateAvailableChecks();
GetItemID RetrieveGetItemIDFromItemID(ItemID itemID); GetItemID RetrieveGetItemIDFromItemID(ItemID itemID);
RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID); RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID);
void ParseArchipelago(); void ParseArchipelago();
bool checkArchipelagoSlotInfo(const char* slotName, const char* roomHash);
void Messagebox_ShowErrorBox(char* title, char* body); void Messagebox_ShowErrorBox(char* title, char* body);
#endif #endif

View File

@@ -154,6 +154,9 @@ SaveManager::SaveManager() {
info.buildVersionMinor = 0; info.buildVersionMinor = 0;
info.buildVersionPatch = 0; info.buildVersionPatch = 0;
memset(&info.buildVersion, 0, sizeof(info.buildVersion)); memset(&info.buildVersion, 0, sizeof(info.buildVersion));
memset(&info.archiUri, 0, sizeof(info.archiUri));
memset(&info.slotName, 0, sizeof(info.slotName));
} }
} }
@@ -509,6 +512,13 @@ void SaveManager::InitMeta(int fileNum) {
fileMetaInfo[fileNum].buildVersionPatch = gSaveContext.ship.stats.buildVersionPatch; fileMetaInfo[fileNum].buildVersionPatch = gSaveContext.ship.stats.buildVersionPatch;
SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].buildVersion, gSaveContext.ship.stats.buildVersion, SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].buildVersion, gSaveContext.ship.stats.buildVersion,
ARRAY_COUNT(fileMetaInfo[fileNum].buildVersion)); ARRAY_COUNT(fileMetaInfo[fileNum].buildVersion));
SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].archiUri, gSaveContext.ship.quest.data.archipelago.archiUri,
ARRAY_COUNT(fileMetaInfo[fileNum].archiUri));
SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].slotName, gSaveContext.ship.quest.data.archipelago.slotName,
ARRAY_COUNT(fileMetaInfo[fileNum].slotName));
SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].archiRoomSeed, gSaveContext.ship.quest.data.archipelago.roomHash,
ARRAY_COUNT(fileMetaInfo[fileNum].archiRoomSeed));
} }
void SaveManager::InitFile(bool isDebug) { void SaveManager::InitFile(bool isDebug) {

View File

@@ -33,6 +33,10 @@ typedef struct {
s32 filenameLanguage; s32 filenameLanguage;
s32 gregFound; s32 gregFound;
s32 hasWallet; s32 hasWallet;
char archiRoomSeed[100];
char slotName[17];
char archiUri[50];
} SaveFileMetaInfo; } SaveFileMetaInfo;
typedef enum { typedef enum {

View File

@@ -2478,7 +2478,8 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
&deathCountSplit[2]); &deathCountSplit[2]);
// draw death count // draw death count
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT) { if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT ||
Save_GetSaveMetaInfo(this->selectedFileIndex)->archiSave) {
for (i = 0, vtxOffset = 0; i < 3; i++, vtxOffset += 4) { for (i = 0, vtxOffset = 0; i < 3; i++, vtxOffset += 4) {
FileChoose_DrawCharacter(this->state.gfxCtx, sp54->fontBuf + deathCountSplit[i] * FONT_CHAR_TEX_SIZE, FileChoose_DrawCharacter(this->state.gfxCtx, sp54->fontBuf + deathCountSplit[i] * FONT_CHAR_TEX_SIZE,
vtxOffset); vtxOffset);
@@ -2504,7 +2505,8 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
i = Save_GetSaveMetaInfo(fileIndex)->healthCapacity / 0x10; i = Save_GetSaveMetaInfo(fileIndex)->healthCapacity / 0x10;
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT) { if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT ||
Save_GetSaveMetaInfo(this->selectedFileIndex)->archiSave) {
// draw hearts // draw hearts
for (vtxOffset = 0, j = 0; j < i; j++, vtxOffset += 4) { for (vtxOffset = 0, j = 0; j < i; j++, vtxOffset += 4) {
gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex] + vtxOffset] + 0x30, 4, 0); gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex] + vtxOffset] + 0x30, 4, 0);
@@ -2521,7 +2523,8 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
textAlpha = 255; textAlpha = 255;
} }
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) != 0 && this->menuMode == FS_MENU_MODE_SELECT) { if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) != 0 && this->menuMode == FS_MENU_MODE_SELECT &&
Save_GetSaveMetaInfo(this->selectedFileIndex)->archiSave == 0) {
DrawMoreInfo(this, fileIndex, textAlpha); DrawMoreInfo(this, fileIndex, textAlpha);
} else { } else {
// draw quest items // draw quest items
@@ -2545,6 +2548,53 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
} }
} }
} }
if(Save_GetSaveMetaInfo(this->selectedFileIndex)->archiSave) {
uint8_t language = (gSaveContext.language == LANGUAGE_JPN) ? LANGUAGE_ENG : gSaveContext.language;
// Connection status text
int statusPos = 61 + Interface_DrawTextLine(this->state.gfxCtx, SohFileSelect_GetArchipelagoSettingText(ASM_STATUS, language),
58, 133, 200, 200, 200, textAlpha, 0.8f, true);
const bool connectedToThisSlot = checkArchipelagoSlotInfo(Save_GetSaveMetaInfo(this->selectedFileIndex)->slotName,
Save_GetSaveMetaInfo(this->selectedFileIndex)->archiRoomSeed);
switch(CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 0)) {
case 0: // Not Connected
Interface_DrawTextLine(this->state.gfxCtx,
SohFileSelect_GetArchipelagoSettingText(ASM_NOT_CONNECTED, language),
statusPos, 133, 255, 120, 120, textAlpha, 0.8f, true);
break;
case 1: // Connecting
case 2: // Connection error, retrying
case 3: // Connected
Interface_DrawTextLine(this->state.gfxCtx,
SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTING, language),
statusPos, 133, 185, 185, 185, textAlpha, 0.8f, true);
break;
case 4: // Connected + Locations Scouted
if(connectedToThisSlot) {
Interface_DrawTextLine(this->state.gfxCtx,
SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTED, language),
statusPos, 133, 120, 255, 120, textAlpha, 0.8f, true);
} else {
Interface_DrawTextLine(this->state.gfxCtx,
SohFileSelect_GetArchipelagoSettingText(ASM_CHAR_SELECT_CONNECTED_TO_OTHER_SLOT, language),
statusPos, 133, 255, 255, 120, textAlpha, 0.8f, true);
}
break;
}
if(!connectedToThisSlot) {
Interface_DrawTextLine(this->state.gfxCtx, SohFileSelect_GetArchipelagoSettingText(ASM_CHAR_START_TO_CONNECT, language),
58, 144, 200, 200, 200, textAlpha, 0.8f, true);
}
//Interface_DrawTextLine(this->state.gfxCtx,
// SohFileSelect_GetArchipelagoSettingText(ASM_CHAR_SELECT_CHANGE_CONNECTION_INFO, language), 95, 220,
// 100, 250, 255, textAlpha, 1.0f, true);
}
} }
CLOSE_DISPS(this->state.gfxCtx); CLOSE_DISPS(this->state.gfxCtx);
@@ -2944,25 +2994,25 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
155, 185, 185, 185, textAlpha, 0.8f, true); 155, 185, 185, 185, textAlpha, 0.8f, true);
// Connection status text // Connection status text
Interface_DrawTextLine(this->state.gfxCtx, SohFileSelect_GetArchipelagoSettingText(ASM_STATUS, language), 70, int statusPos = 75 + Interface_DrawTextLine(this->state.gfxCtx, SohFileSelect_GetArchipelagoSettingText(ASM_STATUS, language), 70,
175, 255, 255, 255, textAlpha, 0.8f, true); 175, 255, 255, 255, textAlpha, 0.8f, true);
switch (CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 0)) { switch (CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 0)) {
case 0: // Not Connected case 0: // Not Connected
Interface_DrawTextLine(this->state.gfxCtx, Interface_DrawTextLine(this->state.gfxCtx,
SohFileSelect_GetArchipelagoSettingText(ASM_NOT_CONNECTED, language), 110, 175, SohFileSelect_GetArchipelagoSettingText(ASM_NOT_CONNECTED, language), statusPos, 175,
255, 120, 120, textAlpha, 0.8f, true); 255, 120, 120, textAlpha, 0.8f, true);
break; break;
case 1: // Connecting case 1: // Connecting
case 2: // Connection error, retrying case 2: // Connection error, retrying
case 3: // Connected case 3: // Connected
Interface_DrawTextLine(this->state.gfxCtx, Interface_DrawTextLine(this->state.gfxCtx,
SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTING, language), 110, 175, 185, SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTING, language), statusPos, 175, 185,
185, 185, textAlpha, 0.8f, true); 185, 185, textAlpha, 0.8f, true);
break; break;
case 4: // Connected + Locations Scouted case 4: // Connected + Locations Scouted
Interface_DrawTextLine(this->state.gfxCtx, Interface_DrawTextLine(this->state.gfxCtx,
SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTED, language), 110, 175, 120, SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTED, language), statusPos, 175, 120,
255, 120, textAlpha, 0.8f, true); 255, 120, textAlpha, 0.8f, true);
break; break;
} }
@@ -3005,7 +3055,7 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
// Draw the small file name box instead when more meta info is enabled // Draw the small file name box instead when more meta info is enabled
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) != 0 && if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) != 0 &&
this->menuMode == FS_MENU_MODE_SELECT) { this->menuMode == FS_MENU_MODE_SELECT && Save_GetSaveMetaInfo(this->selectedFileIndex)->archiSave == 0) {
// Location of file 1 small name box vertices // Location of file 1 small name box vertices
gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[68], 4, 0); gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[68], 4, 0);