Merge pull request #70 from jeromkiller/AddArchipelagoClientLib
Add archipelago client lib
This commit is contained in:
@@ -12,7 +12,7 @@ You can currently connect to the multiworld server, scout the items.
|
|||||||
If you have no randomizer genereted (the `Randomizer` folder is empty) `Connect` to the multiworld from the main screen, click the `Scout` button to load all of the item locations and finally press the `Link up` button, you'll be able to start a randomizer save file.
|
If you have no randomizer genereted (the `Randomizer` folder is empty) `Connect` to the multiworld from the main screen, click the `Scout` button to load all of the item locations and finally press the `Link up` button, you'll be able to start a randomizer save file.
|
||||||
with the items populated with the location from the server.
|
with the items populated with the location from the server.
|
||||||
|
|
||||||
Sending and Recieving should be implemented, Saving the game doesn't save the current item index localy (the library is a bit anoying with that).
|
Sending and Receiving should be implemented, Saving the game doesn't save the current item index localy (the library is a bit anoying with that).
|
||||||
|
|
||||||
Not all checks have been mapped, and some may be mapped incorrectly.
|
Not all checks have been mapped, and some may be mapped incorrectly.
|
||||||
The victory condition should be implemented but has largely gone untested.
|
The victory condition should be implemented but has largely gone untested.
|
||||||
|
|||||||
@@ -71,5 +71,5 @@ DEFINE_HOOK(OnAssetAltChange, ());
|
|||||||
DEFINE_HOOK(OnKaleidoUpdate, ());
|
DEFINE_HOOK(OnKaleidoUpdate, ());
|
||||||
|
|
||||||
DEFINE_HOOK(OnRandomizerItemGivenHooks, (uint32_t rc, GetItemEntry gi, uint8_t isGiSkipped));
|
DEFINE_HOOK(OnRandomizerItemGivenHooks, (uint32_t rc, GetItemEntry gi, uint8_t isGiSkipped));
|
||||||
DEFINE_HOOK(OnArchipelagoItemRecieved, (uint32_t rg));
|
DEFINE_HOOK(OnArchipelagoItemReceived, (uint32_t rg));
|
||||||
DEFINE_HOOK(OnRandomizerExternalCheck, (uint32_t rc));
|
DEFINE_HOOK(OnRandomizerExternalCheck, (uint32_t rc));
|
||||||
|
|||||||
@@ -309,8 +309,8 @@ void GameInteractor_ExecuteOnRandomizerItemGivenHooks(uint32_t rc, GetItemEntry
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Archipelago
|
// MARK: Archipelago
|
||||||
void GameInteractor_ExecuteOnArchipelagoItemRecieved(uint32_t rg) {
|
void GameInteractor_ExecuteOnArchipelagoItemReceived(uint32_t rg) {
|
||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnArchipelagoItemRecieved>(rg);
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnArchipelagoItemReceived>(rg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameInteractor_ExecuteOnRandomizerExternalCheck(uint32_t rc) {
|
void GameInteractor_ExecuteOnRandomizerExternalCheck(uint32_t rc) {
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ void GameInteractor_ExecuteOnKaleidoUpdate();
|
|||||||
void GameInteractor_ExecuteOnRandomizerItemGivenHooks(uint32_t rc, GetItemEntry gi, uint8_t isGiSkipped);
|
void GameInteractor_ExecuteOnRandomizerItemGivenHooks(uint32_t rc, GetItemEntry gi, uint8_t isGiSkipped);
|
||||||
|
|
||||||
// Mark: - Archipelago
|
// Mark: - Archipelago
|
||||||
void GameInteractor_ExecuteOnArchipelagoItemRecieved(uint32_t rg);
|
void GameInteractor_ExecuteOnArchipelagoItemReceived(uint32_t rg);
|
||||||
void GameInteractor_ExecuteOnRandomizerExternalCheck(uint32_t rc);
|
void GameInteractor_ExecuteOnRandomizerExternalCheck(uint32_t rc);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -346,27 +346,27 @@ void Context::SetSpoilerLoaded(const bool spoilerLoaded) {
|
|||||||
mSpoilerLoaded = spoilerLoaded;
|
mSpoilerLoaded = spoilerLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::AddRecievedArchipelagoItem(const RandomizerGet item) {
|
void Context::AddReceivedArchipelagoItem(const RandomizerGet item) {
|
||||||
mAPrecieveQueue.emplace(item);
|
mAPreceiveQueue.emplace(item);
|
||||||
std::string logMessage = "[LOG] Item Pushed: " + item;
|
std::string logMessage = "[LOG] Item Pushed: " + item;
|
||||||
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetItemEntry Context::GetArchipelagoGIEntry() {
|
GetItemEntry Context::GetArchipelagoGIEntry() {
|
||||||
ArchipelagoConsole_SendMessage("[LOG] Trying to get Item Entry", true);
|
ArchipelagoConsole_SendMessage("[LOG] Trying to get Item Entry", true);
|
||||||
if(mAPrecieveQueue.empty()) {
|
if(mAPreceiveQueue.empty()) {
|
||||||
// something must have gone wrong here, just give a rupee
|
// something must have gone wrong here, just give a rupee
|
||||||
return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, GI_HEART);
|
return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, GI_HEART);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the first item from the archipelago queue
|
// get the first item from the archipelago queue
|
||||||
RandomizerGet item_id = mAPrecieveQueue.front();
|
RandomizerGet item_id = mAPreceiveQueue.front();
|
||||||
assert(item_id != RG_NONE);
|
assert(item_id != RG_NONE);
|
||||||
|
|
||||||
Item& item = StaticData::RetrieveItem(item_id);
|
Item& item = StaticData::RetrieveItem(item_id);
|
||||||
SPDLOG_TRACE("Found item! {}, {}", item.GetName().GetEnglish(), (int)item_id);
|
SPDLOG_TRACE("Found item! {}, {}", item.GetName().GetEnglish(), (int)item_id);
|
||||||
GetItemEntry item_entry = item.GetGIEntry_Copy();
|
GetItemEntry item_entry = item.GetGIEntry_Copy();
|
||||||
mAPrecieveQueue.pop();
|
mAPreceiveQueue.pop();
|
||||||
return item_entry; // todo: add custom text maybe?
|
return item_entry; // todo: add custom text maybe?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class Context {
|
|||||||
*/
|
*/
|
||||||
RandoOptionLACSCondition LACSCondition() const;
|
RandoOptionLACSCondition LACSCondition() const;
|
||||||
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
|
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
|
||||||
void AddRecievedArchipelagoItem(const RandomizerGet item);
|
void AddReceivedArchipelagoItem(const RandomizerGet item);
|
||||||
GetItemEntry GetArchipelagoGIEntry();
|
GetItemEntry GetArchipelagoGIEntry();
|
||||||
void ParseSpoiler(const char* spoilerFileName);
|
void ParseSpoiler(const char* spoilerFileName);
|
||||||
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
|
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
|
||||||
@@ -189,6 +189,6 @@ class Context {
|
|||||||
std::string mHash;
|
std::string mHash;
|
||||||
std::string mSeedString;
|
std::string mSeedString;
|
||||||
uint32_t mFinalSeed = 0;
|
uint32_t mFinalSeed = 0;
|
||||||
std::queue<RandomizerGet> mAPrecieveQueue = {};
|
std::queue<RandomizerGet> mAPreceiveQueue = {};
|
||||||
};
|
};
|
||||||
} // namespace Rando
|
} // namespace Rando
|
||||||
@@ -222,11 +222,11 @@ static std::queue<RandomizerCheck> randomizerQueuedChecks;
|
|||||||
static RandomizerCheck randomizerQueuedCheck = RC_UNKNOWN_CHECK;
|
static RandomizerCheck randomizerQueuedCheck = RC_UNKNOWN_CHECK;
|
||||||
static GetItemEntry randomizerQueuedItemEntry = GET_ITEM_NONE;
|
static GetItemEntry randomizerQueuedItemEntry = GET_ITEM_NONE;
|
||||||
|
|
||||||
void ArchipelagoOnRecieveItem(const int32_t item) {
|
void ArchipelagoOnReceiveItem(const int32_t item) {
|
||||||
std::string logMessage = "[LOG] Receive item handler called: " + item;
|
std::string logMessage = "[LOG] Receive item handler called: " + item;
|
||||||
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
||||||
randomizerQueuedChecks.push(RC_ARCHIPELAGO_RECIEVED_ITEM);
|
randomizerQueuedChecks.push(RC_ARCHIPELAGO_RECEIVED_ITEM);
|
||||||
Rando::Context::GetInstance()->AddRecievedArchipelagoItem(static_cast<RandomizerGet>(item));
|
Rando::Context::GetInstance()->AddReceivedArchipelagoItem(static_cast<RandomizerGet>(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) {
|
void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) {
|
||||||
@@ -313,7 +313,7 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() {
|
|||||||
auto loc = Rando::Context::GetInstance()->GetItemLocation(rc);
|
auto loc = Rando::Context::GetInstance()->GetItemLocation(rc);
|
||||||
uint8_t isGiSkipped = 0;
|
uint8_t isGiSkipped = 0;
|
||||||
|
|
||||||
if (rc == RC_ARCHIPELAGO_RECIEVED_ITEM) {
|
if (rc == RC_ARCHIPELAGO_RECEIVED_ITEM) {
|
||||||
getItemEntry = Rando::Context::GetInstance()->GetArchipelagoGIEntry();
|
getItemEntry = Rando::Context::GetInstance()->GetArchipelagoGIEntry();
|
||||||
} else {
|
} else {
|
||||||
RandomizerGet vanillaRandomizerGet = Rando::StaticData::GetLocation(rc)->GetVanillaItem();
|
RandomizerGet vanillaRandomizerGet = Rando::StaticData::GetLocation(rc)->GetVanillaItem();
|
||||||
@@ -2540,7 +2540,7 @@ void RandomizerRegisterHooks() {
|
|||||||
onCuccoOrChickenHatchHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnCuccoOrChickenHatch>(
|
onCuccoOrChickenHatchHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnCuccoOrChickenHatch>(
|
||||||
RandomizerOnCuccoOrChickenHatch);
|
RandomizerOnCuccoOrChickenHatch);
|
||||||
|
|
||||||
COND_HOOK(GameInteractor::OnArchipelagoItemRecieved, IS_ARCHIPELAGO, ArchipelagoOnRecieveItem);
|
COND_HOOK(GameInteractor::OnArchipelagoItemReceived, IS_ARCHIPELAGO, ArchipelagoOnReceiveItem);
|
||||||
COND_HOOK(GameInteractor::OnRandomizerExternalCheck, IS_ARCHIPELAGO, RandomizerOnExternalCheckHandler)
|
COND_HOOK(GameInteractor::OnRandomizerExternalCheck, IS_ARCHIPELAGO, RandomizerOnExternalCheckHandler)
|
||||||
|
|
||||||
if (RAND_GET_OPTION(RSK_FISHSANITY) != RO_FISHSANITY_OFF) {
|
if (RAND_GET_OPTION(RSK_FISHSANITY) != RO_FISHSANITY_OFF) {
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ bool ItemLocation::HasObtained() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ItemLocation::SetCheckStatus(RandomizerCheckStatus status_) {
|
void ItemLocation::SetCheckStatus(RandomizerCheckStatus status_) {
|
||||||
if(rc == RC_ARCHIPELAGO_RECIEVED_ITEM) // never count the AP recieve trigger as 'collected'
|
if(rc == RC_ARCHIPELAGO_RECEIVED_ITEM) // never count the AP receive trigger as 'collected'
|
||||||
return;
|
return;
|
||||||
status = status_;
|
status = status_;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3472,7 +3472,7 @@ typedef enum {
|
|||||||
RC_DEKU_TREE_QUEEN_GOHMA_GRASS_8,
|
RC_DEKU_TREE_QUEEN_GOHMA_GRASS_8,
|
||||||
// End Grass
|
// End Grass
|
||||||
|
|
||||||
RC_ARCHIPELAGO_RECIEVED_ITEM,
|
RC_ARCHIPELAGO_RECEIVED_ITEM,
|
||||||
RC_MAX
|
RC_MAX
|
||||||
} RandomizerCheck;
|
} RandomizerCheck;
|
||||||
|
|
||||||
|
|||||||
@@ -29,10 +29,7 @@ ArchipelagoClient::ArchipelagoClient() {
|
|||||||
|
|
||||||
gameWon = false;
|
gameWon = false;
|
||||||
itemQueued = false;
|
itemQueued = false;
|
||||||
|
disconnecting = 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() {
|
ArchipelagoClient& ArchipelagoClient::GetInstance() {
|
||||||
@@ -45,6 +42,7 @@ bool ArchipelagoClient::StartClient() {
|
|||||||
apClient.reset();
|
apClient.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disconnecting = false;
|
||||||
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"));
|
CVarGetString(CVAR_REMOTE_ARCHIPELAGO("ServerAddress"), "localhost:38281"), "cacert.pem"));
|
||||||
@@ -66,12 +64,22 @@ bool ArchipelagoClient::StartClient() {
|
|||||||
// if we are already in game when we connect
|
// if we are already in game when we connect
|
||||||
// we won't have to request an itemSynch
|
// we won't have to request an itemSynch
|
||||||
if(GameInteractor::IsSaveLoaded(true)) {
|
if(GameInteractor::IsSaveLoaded(true)) {
|
||||||
|
if(!isRightSaveLoaded()) {
|
||||||
|
disconnecting = true;
|
||||||
|
ArchipelagoConsole_SendMessage("[ERROR] Connected to incorrect slot, disconnecting...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SynchSentLocations();
|
SynchSentLocations();
|
||||||
SynchRecievedLocations();
|
SynchReceivedLocations();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apClient->set_items_received_handler([&](const std::list<APClient::NetworkItem>& items) {
|
apClient->set_items_received_handler([&](const std::list<APClient::NetworkItem>& items) {
|
||||||
|
if(disconnecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(const APClient::NetworkItem& item : items) {
|
for(const APClient::NetworkItem& item : items) {
|
||||||
ApItem apItem;
|
ApItem apItem;
|
||||||
const std::string game = apClient->get_player_game(item.player);
|
const std::string game = apClient->get_player_game(item.player);
|
||||||
@@ -85,6 +93,10 @@ bool ArchipelagoClient::StartClient() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
apClient->set_location_info_handler([&](const std::list<APClient::NetworkItem>& items) {
|
apClient->set_location_info_handler([&](const std::list<APClient::NetworkItem>& items) {
|
||||||
|
if(disconnecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
scoutedItems.clear();
|
scoutedItems.clear();
|
||||||
|
|
||||||
for(const APClient::NetworkItem& item: items) {
|
for(const APClient::NetworkItem& item: items) {
|
||||||
@@ -108,25 +120,71 @@ bool ArchipelagoClient::StartClient() {
|
|||||||
}); // todo maybe move these functions to a lambda, since they don't have to be static anymore
|
}); // 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<int64_t> locations) {
|
apClient->set_location_checked_handler([&](const std::list<int64_t> locations) {
|
||||||
|
if(disconnecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(const int64_t apLoc : locations) {
|
for(const int64_t apLoc : locations) {
|
||||||
QueueExternalCheck(apLoc);
|
QueueExternalCheck(apLoc);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apClient->set_print_json_handler([&](const APClient::PrintJSONArgs& arg) {
|
apClient->set_print_json_handler([&](const APClient::PrintJSONArgs& arg) {
|
||||||
std::string tag = "[" + arg.type + "] ";
|
if(disconnecting) {
|
||||||
|
return;
|
||||||
const int slot = apClient->get_player_number();
|
|
||||||
if(arg.type == "ItemSend") {
|
|
||||||
if((*arg.item).player == slot) {
|
|
||||||
tag = "[Found] ";
|
|
||||||
} else if (*arg.receiving == slot ) {
|
|
||||||
tag = "[Received] ";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string text = tag + apClient->render_json(arg.data, APClient::RenderFormat::TEXT);
|
std::vector<ColoredTextNode> coloredNodes;
|
||||||
ArchipelagoConsole_SendMessage(text.c_str(), false);
|
|
||||||
|
for(const APClient::TextNode& node : arg.data) {
|
||||||
|
APClient* client = apClient.get();
|
||||||
|
std::string color;
|
||||||
|
std::string text;
|
||||||
|
|
||||||
|
if(node.type == "player_id") {
|
||||||
|
int id = std::stoi(node.text);
|
||||||
|
if (color.empty() && id == client->get_player_number()) color = "magenta";
|
||||||
|
else if(color.empty()) color = "yellow";
|
||||||
|
text = client->get_player_alias(id);
|
||||||
|
} else if (node.type == "item_id") {
|
||||||
|
int64_t id = std::stoll(node.text);
|
||||||
|
if(color.empty()) {
|
||||||
|
if (node.flags & APClient::ItemFlags::FLAG_ADVANCEMENT) color = "plum";
|
||||||
|
else if (node.flags & APClient::ItemFlags::FLAG_NEVER_EXCLUDE) color = "slateblue";
|
||||||
|
else if (node.flags & APClient::ItemFlags::FLAG_TRAP) color = "salmon";
|
||||||
|
else color = "cyan";
|
||||||
|
}
|
||||||
|
text = client->get_item_name(id, client->get_player_game(node.player));
|
||||||
|
} else if (node.type == "location_id") {
|
||||||
|
int64_t id = std::stoll(node.text);
|
||||||
|
if (color.empty()) color = "blue";
|
||||||
|
text = client->get_location_name(id, client->get_player_game(node.player));
|
||||||
|
} else if (node.type == "hint_status") {
|
||||||
|
text = node.text;
|
||||||
|
if (node.hintStatus == APClient::HINT_FOUND) color = "green";
|
||||||
|
else if (node.hintStatus == APClient::HINT_UNSPECIFIED) color = "grey";
|
||||||
|
else if (node.hintStatus == APClient::HINT_NO_PRIORITY) color = "slateblue";
|
||||||
|
else if (node.hintStatus == APClient::HINT_AVOID) color = "salmon";
|
||||||
|
else if (node.hintStatus == APClient::HINT_PRIORITY) color = "plum";
|
||||||
|
else color = "red"; // unknown status -> red
|
||||||
|
} else if (node.type == "ERROR") {
|
||||||
|
color = "ERROR";
|
||||||
|
text = node.text;
|
||||||
|
} else if (node.type == "LOG") {
|
||||||
|
color = "LOG";
|
||||||
|
text = node.text;
|
||||||
|
} else {
|
||||||
|
color = "white";
|
||||||
|
text = node.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColoredTextNode Colornode;
|
||||||
|
Colornode.color = color;
|
||||||
|
Colornode.text = text;
|
||||||
|
coloredNodes.push_back(Colornode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArchipelagoConsole_PrintJson(coloredNodes);
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -139,7 +197,14 @@ void ArchipelagoClient::GameLoaded() {
|
|||||||
|
|
||||||
// if its not an AP save, disconnect
|
// if its not an AP save, disconnect
|
||||||
if(!IS_ARCHIPELAGO) {
|
if(!IS_ARCHIPELAGO) {
|
||||||
apClient->reset();
|
ArchipelagoConsole_SendMessage("[ERROR] Loaded save is not not an archipelago save, disconnecting...");
|
||||||
|
disconnecting = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isRightSaveLoaded()) {
|
||||||
|
ArchipelagoConsole_SendMessage("[ERROR] Loaded save is not associated with connected slot, disconnecting...");
|
||||||
|
disconnecting = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +212,7 @@ void ArchipelagoClient::GameLoaded() {
|
|||||||
|
|
||||||
SynchItems();
|
SynchItems();
|
||||||
SynchSentLocations();
|
SynchSentLocations();
|
||||||
SynchRecievedLocations();
|
SynchReceivedLocations();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchipelagoClient::StartLocationScouts() {
|
void ArchipelagoClient::StartLocationScouts() {
|
||||||
@@ -185,7 +250,7 @@ void ArchipelagoClient::SynchSentLocations() {
|
|||||||
apClient->LocationChecks(checkedLocations);
|
apClient->LocationChecks(checkedLocations);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchipelagoClient::SynchRecievedLocations() {
|
void ArchipelagoClient::SynchReceivedLocations() {
|
||||||
// Open checks that have been found previously but went unsaved
|
// Open checks that have been found previously but went unsaved
|
||||||
for(const int64_t apLoc : apClient->get_checked_locations()) {
|
for(const int64_t apLoc : apClient->get_checked_locations()) {
|
||||||
QueueExternalCheck(apLoc);
|
QueueExternalCheck(apLoc);
|
||||||
@@ -196,12 +261,17 @@ void ArchipelagoClient::QueueExternalCheck(const int64_t apLocation) {
|
|||||||
const std::string checkName = apClient->get_location_name(apLocation, AP_Client_consts::AP_GAME_NAME);
|
const std::string checkName = apClient->get_location_name(apLocation, AP_Client_consts::AP_GAME_NAME);
|
||||||
const uint32_t RC = static_cast<uint32_t>(Rando::StaticData::locationNameToEnum[checkName]);
|
const uint32_t RC = static_cast<uint32_t>(Rando::StaticData::locationNameToEnum[checkName]);
|
||||||
|
|
||||||
|
if(RC == RC_UNKNOWN_CHECK) {
|
||||||
|
ArchipelagoConsole_SendMessage("[ERROR] Attempting to queue RC_UNKOWN_CHECK, skipping", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Don't queue checks we already have
|
// Don't queue checks we already have
|
||||||
if(Rando::Context::GetInstance()->GetItemLocation(RC)->HasObtained()) {
|
if(Rando::Context::GetInstance()->GetItemLocation(RC)->HasObtained()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string locationLog = "[LOG] Externaly checking" + checkName;
|
std::string locationLog = "[LOG] Externaly checking: " + checkName;
|
||||||
ArchipelagoConsole_SendMessage(locationLog.c_str(), true);
|
ArchipelagoConsole_SendMessage(locationLog.c_str(), true);
|
||||||
|
|
||||||
GameInteractor_ExecuteOnRandomizerExternalCheck(RC);
|
GameInteractor_ExecuteOnRandomizerExternalCheck(RC);
|
||||||
@@ -212,12 +282,17 @@ bool ArchipelagoClient::IsConnected() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ArchipelagoClient::CheckLocation(RandomizerCheck sohCheckId) {
|
void ArchipelagoClient::CheckLocation(RandomizerCheck sohCheckId) {
|
||||||
|
if(sohCheckId == RC_UNKNOWN_CHECK) {
|
||||||
|
ArchipelagoConsole_SendMessage("[ERROR] trying to send RC_UNKNOWN_CHECK, skipping", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::string apName = Rando::StaticData::GetLocation(sohCheckId)->GetName();
|
std::string apName = Rando::StaticData::GetLocation(sohCheckId)->GetName();
|
||||||
if (apName.empty()) {
|
if (apName.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int64_t apItemId = apClient->get_location_id(std::string(apName));
|
|
||||||
|
|
||||||
|
int64_t apItemId = apClient->get_location_id(std::string(apName));
|
||||||
std::string logMessage = "[LOG] Checked: " + apName + "(" + std::to_string(apItemId) + "), sending to AP server";
|
std::string logMessage = "[LOG] Checked: " + apName + "(" + std::to_string(apItemId) + "), sending to AP server";
|
||||||
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
||||||
|
|
||||||
@@ -234,21 +309,21 @@ void ArchipelagoClient::OnItemReceived(const ApItem apItem) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string logMessage = "[LOG] Recieved " + apItem.itemName;
|
std::string logMessage = "[LOG] Received " + apItem.itemName;
|
||||||
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
||||||
|
|
||||||
// add item to the queue
|
if(apItem.index < gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex) {
|
||||||
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
|
// Skip queueing any items we already have
|
||||||
std::string logMessage = "[LOG] Skipping giving " + item.itemName + ". We recieved this previously.";
|
std::string logMessage = "[LOG] Skipping giving " + apItem.itemName + ". We received this previously.";
|
||||||
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add item to the queue
|
||||||
|
receiveQueue.push(apItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchipelagoClient::QueueItem(const ApItem item) {
|
||||||
std::string logMessage = "[LOG] Giving " + item.itemName;
|
std::string logMessage = "[LOG] Giving " + item.itemName;
|
||||||
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
||||||
const RandomizerGet RG = Rando::StaticData::itemNameToEnum[item.itemName];
|
const RandomizerGet RG = Rando::StaticData::itemNameToEnum[item.itemName];
|
||||||
@@ -257,7 +332,7 @@ void ArchipelagoClient::QueueItem(const ApItem item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
itemQueued = true;
|
itemQueued = true;
|
||||||
GameInteractor_ExecuteOnArchipelagoItemRecieved(static_cast<int32_t>(RG));
|
GameInteractor_ExecuteOnArchipelagoItemReceived(static_cast<int32_t>(RG));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchipelagoClient::SendGameWon() {
|
void ArchipelagoClient::SendGameWon() {
|
||||||
@@ -267,22 +342,49 @@ void ArchipelagoClient::SendGameWon() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArchipelagoClient::SendMessage(const std::string message) {
|
||||||
|
// local commands not implemented yet
|
||||||
|
if(message.starts_with("/")) {
|
||||||
|
ArchipelagoConsole_SendMessage("Ship of Harkinian does not have any local commands yet.\nUse !help\" to see server commands instead", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(apClient == nullptr) {
|
||||||
|
ArchipelagoConsole_SendMessage("[ERROR] Could not send message. Please Connect to your slot.", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
apClient->Say(message);
|
||||||
|
}
|
||||||
|
|
||||||
void ArchipelagoClient::Poll() {
|
void ArchipelagoClient::Poll() {
|
||||||
if(apClient == nullptr) {
|
if(apClient == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// queue another item to be recieved
|
if(disconnecting) {
|
||||||
if(!itemQueued && recieveQueue.size() > 0) {
|
apClient->reset();
|
||||||
|
apClient = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// queue another item to be received
|
||||||
|
if(!itemQueued && receiveQueue.size() > 0) {
|
||||||
|
|
||||||
const ApItem item = recieveQueue.front();
|
const ApItem item = receiveQueue.front();
|
||||||
recieveQueue.pop();
|
receiveQueue.pop();
|
||||||
QueueItem(item);
|
QueueItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
apClient->poll();
|
apClient->poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ArchipelagoClient::isRightSaveLoaded() const {
|
||||||
|
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;
|
||||||
|
return seedMatch && slotMatch;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string ArchipelagoClient::GetSlotName() const {
|
const std::string ArchipelagoClient::GetSlotName() const {
|
||||||
if(apClient == NULL) {
|
if(apClient == NULL) {
|
||||||
return "";
|
return "";
|
||||||
@@ -301,7 +403,7 @@ const std::vector<ArchipelagoClient::ApItem>& ArchipelagoClient::GetScoutedItems
|
|||||||
|
|
||||||
const char* ArchipelagoClient::GetConnectionStatus() {
|
const char* ArchipelagoClient::GetConnectionStatus() {
|
||||||
if (!apClient) {
|
if (!apClient) {
|
||||||
return "";
|
return "Disconnected!";
|
||||||
}
|
}
|
||||||
|
|
||||||
APClient::State clientStatus = apClient->get_state();
|
APClient::State clientStatus = apClient->get_state();
|
||||||
@@ -317,7 +419,7 @@ const char* ArchipelagoClient::GetConnectionStatus() {
|
|||||||
return "Socket Connected!";
|
return "Socket Connected!";
|
||||||
}
|
}
|
||||||
case APClient::State::ROOM_INFO: {
|
case APClient::State::ROOM_INFO: {
|
||||||
return "Room info Recieved!";
|
return "Room info Received!";
|
||||||
}
|
}
|
||||||
case APClient::State::SLOT_CONNECTED: {
|
case APClient::State::SLOT_CONNECTED: {
|
||||||
return "Slot Connected!";
|
return "Slot Connected!";
|
||||||
@@ -335,6 +437,12 @@ extern "C" void Archipelago_InitSaveFile() {
|
|||||||
|
|
||||||
std::vector<ArchipelagoClient::ApItem> scoutedItems = ArchipelagoClient::GetInstance().GetScoutedItems();
|
std::vector<ArchipelagoClient::ApItem> scoutedItems = ArchipelagoClient::GetInstance().GetScoutedItems();
|
||||||
|
|
||||||
|
ArchipelagoClient& client = ArchipelagoClient::GetInstance();
|
||||||
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.roomHash, client.apClient->get_seed(),
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash));
|
||||||
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.slotName, client.apClient->get_slot(),
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
|
||||||
|
|
||||||
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];
|
||||||
|
|
||||||
@@ -411,11 +519,16 @@ void InitArchipelagoData(bool isDebug) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RegisterArchipelago() {
|
void RegisterArchipelago() {
|
||||||
|
// make sure the client is constructed
|
||||||
|
ArchipelagoClient::GetInstance();
|
||||||
|
|
||||||
CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0);
|
CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("Connected"), 0);
|
||||||
|
|
||||||
|
COND_HOOK(GameInteractor::OnGameFrameUpdate, true, [](){ArchipelagoClient::GetInstance().Poll();});
|
||||||
|
COND_HOOK(GameInteractor::OnLoadGame, true, [](int32_t file_id){ArchipelagoClient::GetInstance().GameLoaded();});
|
||||||
COND_HOOK(GameInteractor::OnRandomizerItemGivenHooks, IS_ARCHIPELAGO,
|
COND_HOOK(GameInteractor::OnRandomizerItemGivenHooks, IS_ARCHIPELAGO,
|
||||||
[](uint32_t rc, GetItemEntry gi, uint8_t isGiSkipped) {
|
[](uint32_t rc, GetItemEntry gi, uint8_t isGiSkipped) {
|
||||||
if (rc == RC_ARCHIPELAGO_RECIEVED_ITEM) {
|
if (rc == RC_ARCHIPELAGO_RECEIVED_ITEM) {
|
||||||
gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex++;
|
gSaveContext.ship.quest.data.archipelago.lastReceivedItemIndex++;
|
||||||
ArchipelagoClient::GetInstance().itemQueued = false;
|
ArchipelagoClient::GetInstance().itemQueued = false;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ class ArchipelagoClient{
|
|||||||
uint64_t index;
|
uint64_t index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ColoredTextNode {
|
||||||
|
std::string text;
|
||||||
|
std::string color;
|
||||||
|
};
|
||||||
|
|
||||||
static ArchipelagoClient& GetInstance();
|
static ArchipelagoClient& GetInstance();
|
||||||
|
|
||||||
bool StartClient();
|
bool StartClient();
|
||||||
@@ -36,7 +41,7 @@ class ArchipelagoClient{
|
|||||||
void StartLocationScouts();
|
void StartLocationScouts();
|
||||||
void SynchItems();
|
void SynchItems();
|
||||||
void SynchSentLocations();
|
void SynchSentLocations();
|
||||||
void SynchRecievedLocations();
|
void SynchReceivedLocations();
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
const std::string GetSlotName() const;
|
const std::string GetSlotName() const;
|
||||||
@@ -53,11 +58,12 @@ class ArchipelagoClient{
|
|||||||
void QueueExternalCheck(int64_t apLocation);
|
void QueueExternalCheck(int64_t apLocation);
|
||||||
|
|
||||||
void SendGameWon();
|
void SendGameWon();
|
||||||
|
void SendMessage(const std::string message);
|
||||||
void Poll();
|
void Poll();
|
||||||
|
|
||||||
std::unique_ptr<APClient> apClient;
|
std::unique_ptr<APClient> apClient;
|
||||||
bool itemQueued;
|
bool itemQueued;
|
||||||
|
bool disconnecting;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ArchipelagoClient();
|
ArchipelagoClient();
|
||||||
@@ -65,9 +71,12 @@ class ArchipelagoClient{
|
|||||||
private:
|
private:
|
||||||
ArchipelagoClient(ArchipelagoClient &) = delete;
|
ArchipelagoClient(ArchipelagoClient &) = delete;
|
||||||
void operator=(const ArchipelagoClient &) = delete;
|
void operator=(const ArchipelagoClient &) = delete;
|
||||||
|
|
||||||
|
bool isRightSaveLoaded() const;
|
||||||
|
|
||||||
std::string uuid;
|
std::string uuid;
|
||||||
|
|
||||||
static std::shared_ptr<ArchipelagoClient> instance; // is this even used?
|
static std::shared_ptr<ArchipelagoClient> instance;
|
||||||
static bool initialized;
|
static bool initialized;
|
||||||
|
|
||||||
bool gameWon;
|
bool gameWon;
|
||||||
@@ -75,7 +84,7 @@ class ArchipelagoClient{
|
|||||||
nlohmann::json slotData;
|
nlohmann::json slotData;
|
||||||
std::set<int64_t> locations;
|
std::set<int64_t> locations;
|
||||||
std::vector<ApItem> scoutedItems;
|
std::vector<ApItem> scoutedItems;
|
||||||
std::queue<ApItem> recieveQueue;
|
std::queue<ApItem> receiveQueue;
|
||||||
};
|
};
|
||||||
|
|
||||||
void LoadArchipelagoData();
|
void LoadArchipelagoData();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "soh/SohGui/SohGui.hpp"
|
#include "soh/SohGui/SohGui.hpp"
|
||||||
#include "soh/OTRGlobals.h"
|
#include "soh/OTRGlobals.h"
|
||||||
|
|
||||||
ImVector<char*> Items;
|
std::vector<std::vector<ArchipelagoClient::ColoredTextNode>> Items;
|
||||||
bool autoScroll = true;
|
bool autoScroll = true;
|
||||||
|
|
||||||
using namespace UIWidgets;
|
using namespace UIWidgets;
|
||||||
@@ -19,7 +19,21 @@ void ArchipelagoConsole_SendMessage(const char* fmt, bool debugMessage, ...) {
|
|||||||
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
|
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
|
||||||
buf[IM_ARRAYSIZE(buf) - 1] = 0;
|
buf[IM_ARRAYSIZE(buf) - 1] = 0;
|
||||||
va_end(args);
|
va_end(args);
|
||||||
Items.push_back(strdup(buf));
|
ArchipelagoClient::ColoredTextNode node;
|
||||||
|
node.text = std::string(buf);
|
||||||
|
node.color = "white";
|
||||||
|
if (strstr(buf, "[ERROR]")) {
|
||||||
|
node.color = "ERROR";
|
||||||
|
} else if (strstr(buf, "[LOG]")) {
|
||||||
|
node.color = "LOG";
|
||||||
|
}
|
||||||
|
std::vector<ArchipelagoClient::ColoredTextNode> line;
|
||||||
|
line.push_back(node);
|
||||||
|
Items.push_back(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchipelagoConsole_PrintJson(const std::vector<ArchipelagoClient::ColoredTextNode> nodes) {
|
||||||
|
Items.push_back(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchipelagoConsoleWindow::DrawElement() {
|
void ArchipelagoConsoleWindow::DrawElement() {
|
||||||
@@ -28,57 +42,19 @@ void ArchipelagoConsoleWindow::DrawElement() {
|
|||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.15f, 0.15f, 0.15f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.15f, 0.15f, 0.15f, 1.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 8.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 8.0f);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15.0f, 12.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15.0f, 12.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 1.0f));
|
||||||
|
|
||||||
if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, 400), ImGuiChildFlags_AlwaysUseWindowPadding,
|
if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, 400), ImGuiChildFlags_AlwaysUseWindowPadding,
|
||||||
ImGuiWindowFlags_HorizontalScrollbar)) {
|
ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||||
|
|
||||||
for (int i = 0; i < Items.Size; i++) {
|
for(const std::vector<ArchipelagoClient::ColoredTextNode>& line : Items) {
|
||||||
const char* item = Items[i];
|
for(const ArchipelagoClient::ColoredTextNode& node : line) {
|
||||||
ImVec4 color;
|
ImGui::PushStyleColor(ImGuiCol_Text, getColorVal(node.color));
|
||||||
bool hasColor = false;
|
ImGui::TextUnformatted(node.text.c_str());
|
||||||
if (strstr(item, "[ERROR]")) {
|
ImGui::SameLine();
|
||||||
color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f);
|
|
||||||
hasColor = true;
|
|
||||||
} else if (strstr(item, "[LOG]")) {
|
|
||||||
color = ImVec4(0.7f, 0.7f, 1.0f, 1.0f);
|
|
||||||
hasColor = true;
|
|
||||||
} else if (strstr(item, "[Found]")) {
|
|
||||||
color = ImVec4(0.24f, 0.64f, 0.69f, 1.00f);
|
|
||||||
hasColor = true;
|
|
||||||
} else if (strstr(item, "[Received]")) {
|
|
||||||
color = ImVec4(0.18f, 0.76f, 0.42f, 1.00f);
|
|
||||||
hasColor = true;
|
|
||||||
} else if (strstr(item, "[ItemCheat]")) {
|
|
||||||
color = ImVec4(0.97f, 0.26f, 0.26f, 1.00f);
|
|
||||||
hasColor = true;
|
|
||||||
} else if (strstr(item, "[Hint]")) {
|
|
||||||
color = ImVec4(0.89f, 0.45f, 1.00f, 1.00f);
|
|
||||||
hasColor = true;
|
|
||||||
} else if (strstr(item, "[Join]")) {
|
|
||||||
color = ImVec4(0.00f, 0.80f, 0.11f, 1.00f);
|
|
||||||
hasColor = true;
|
|
||||||
} else if (strstr(item, "[Part]")) {
|
|
||||||
color = ImVec4(1.00f, 0.01f, 0.01f, 1.00f);
|
|
||||||
hasColor = true;
|
|
||||||
} else if (strstr(item, "[Goal]")) {
|
|
||||||
color = ImVec4(0.00f, 0.70f, 0.21f, 1.00f);
|
|
||||||
hasColor = true;
|
|
||||||
} else if (strstr(item, "[Release]")) {
|
|
||||||
color = ImVec4(0.51f, 0.21f, 0.61f, 1.00f);
|
|
||||||
hasColor = true;
|
|
||||||
} else if (strstr(item, "[Collect]")) {
|
|
||||||
color = ImVec4(0.51f, 0.21f, 0.61f, 1.00f);
|
|
||||||
hasColor = true;
|
|
||||||
}
|
|
||||||
if (hasColor) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TextUnformatted(item);
|
|
||||||
|
|
||||||
if (hasColor) {
|
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
}
|
}
|
||||||
|
ImGui::NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep up at the bottom of the scroll region if we were already at the bottom at the beginning of the frame.
|
// Keep up at the bottom of the scroll region if we were already at the bottom at the beginning of the frame.
|
||||||
@@ -89,5 +65,58 @@ void ArchipelagoConsoleWindow::DrawElement() {
|
|||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::PopStyleVar(3);
|
||||||
|
|
||||||
|
static char textEntryBuf[1024];
|
||||||
|
static bool keepFocus = false;
|
||||||
|
|
||||||
|
if(keepFocus) {
|
||||||
|
ImGui::SetKeyboardFocusHere();
|
||||||
|
keepFocus = false;
|
||||||
|
}
|
||||||
|
if(ImGui::InputText("##AP_MessageField", textEntryBuf, 1023, ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||||
|
ArchipelagoClient::GetInstance().SendMessage(std::string(textEntryBuf));
|
||||||
|
textEntryBuf[0] = '\0';
|
||||||
|
keepFocus = true;
|
||||||
|
}
|
||||||
|
//keepFocus = ImGui::IsItemActive();
|
||||||
|
ImGui::SameLine();
|
||||||
|
if(ImGui::Button("Send")) {
|
||||||
|
ArchipelagoClient::GetInstance().SendMessage(std::string(textEntryBuf));
|
||||||
|
textEntryBuf[0] = '\0';
|
||||||
|
keepFocus = true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ImVec4 getColorVal(const std::string& color) { // TODO change color strings to an enum
|
||||||
|
if (color == "ERROR") {
|
||||||
|
return ImVec4(1.0f, 0.4f, 0.4f, 1.0f);
|
||||||
|
} else if(color =="LOG") {
|
||||||
|
return ImVec4(0.7f, 0.7f, 1.0f, 1.0f);
|
||||||
|
} else if(color == "black") {
|
||||||
|
return ImVec4(0.000f, 0.000f, 0.000f, 1.00f);
|
||||||
|
} else if(color == "red") {
|
||||||
|
return ImVec4(0.933f, 0.000f, 0.000f, 1.00f);
|
||||||
|
} else if(color == "green") {
|
||||||
|
return ImVec4(0.000f, 1.000f, 0.498f, 1.00f);
|
||||||
|
} else if(color == "yellow") {
|
||||||
|
return ImVec4(0.980f, 0.980f, 0.824f, 1.00f);
|
||||||
|
} else if(color == "blue") {
|
||||||
|
return ImVec4(0.392f, 0.584f, 0.929f, 1.00f);
|
||||||
|
} else if(color == "cyan") {
|
||||||
|
return ImVec4(0.000f, 0.933f, 0.933f, 1.00f);
|
||||||
|
} else if(color == "magenta") {
|
||||||
|
return ImVec4(0.933f, 0.000f, 0.933f, 1.00f);
|
||||||
|
} else if(color == "slateblue") {
|
||||||
|
return ImVec4(0.427f, 0.545f, 0.910f, 1.00f);
|
||||||
|
} else if(color == "plum") {
|
||||||
|
return ImVec4(0.686f, 0.600f, 0.937f, 1.00f);
|
||||||
|
} else if(color == "salmon") {
|
||||||
|
return ImVec4(0.980f, 0.502f, 0.447f, 1.00f);
|
||||||
|
} else if(color == "white") {
|
||||||
|
return ImVec4(0.93f, 0.93f, 0.93f, 1.00f);
|
||||||
|
} else if(color == "orange") {
|
||||||
|
return ImVec4(1.000, 0.467f, 0.000f, 1.000f);
|
||||||
|
}
|
||||||
|
return ImVec4(0.93f, 0.93f, 0.93f, 1.00f);
|
||||||
|
}
|
||||||
@@ -3,6 +3,9 @@
|
|||||||
#define ARCHIPELAGO_CONSOLE_WINDOW_H
|
#define ARCHIPELAGO_CONSOLE_WINDOW_H
|
||||||
|
|
||||||
#include <libultraship/libultraship.h>
|
#include <libultraship/libultraship.h>
|
||||||
|
#include "Archipelago.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
class ArchipelagoConsoleWindow final : public Ship::GuiWindow {
|
class ArchipelagoConsoleWindow final : public Ship::GuiWindow {
|
||||||
public:
|
public:
|
||||||
@@ -16,5 +19,7 @@ class ArchipelagoConsoleWindow final : public Ship::GuiWindow {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void ArchipelagoConsole_SendMessage(const char* fmt, bool debugMessage = false, ...);
|
void ArchipelagoConsole_SendMessage(const char* fmt, bool debugMessage = false, ...);
|
||||||
|
void ArchipelagoConsole_PrintJson(const std::vector<ArchipelagoClient::ColoredTextNode> nodes);
|
||||||
|
ImVec4 getColorVal(const std::string& color);
|
||||||
|
|
||||||
#endif // ARCHIPELAGO_CONSOLE_WINDOW_H
|
#endif // ARCHIPELAGO_CONSOLE_WINDOW_H
|
||||||
Reference in New Issue
Block a user