diff options
| author | Star Rauchenberger <fefferburbia@gmail.com> | 2024-06-06 15:54:41 -0400 |
|---|---|---|
| committer | Star Rauchenberger <fefferburbia@gmail.com> | 2024-06-06 15:54:41 -0400 |
| commit | 8ddab49cc13d809ca75dcd7f645661a3d3cb05c4 (patch) | |
| tree | ba1e5f3237dbb7cdc939c35e193f5e6e46845a77 /src/ap_state.cpp | |
| parent | ac38dd0a5c394eefc39b7a8cf7b96762f18c8b31 (diff) | |
| parent | 6f5287b3921c843a6b322ccbdfcbef00a8f16980 (diff) | |
| download | lingo-ap-tracker-8ddab49cc13d809ca75dcd7f645661a3d3cb05c4.tar.gz lingo-ap-tracker-8ddab49cc13d809ca75dcd7f645661a3d3cb05c4.tar.bz2 lingo-ap-tracker-8ddab49cc13d809ca75dcd7f645661a3d3cb05c4.zip | |
Merge branch 'subway'
Diffstat (limited to 'src/ap_state.cpp')
| -rw-r--r-- | src/ap_state.cpp | 120 |
1 files changed, 87 insertions, 33 deletions
| diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 8feb78b..0ce4582 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <tuple> | 21 | #include <tuple> |
| 22 | 22 | ||
| 23 | #include "game_data.h" | 23 | #include "game_data.h" |
| 24 | #include "logger.h" | ||
| 25 | #include "tracker_frame.h" | 24 | #include "tracker_frame.h" |
| 26 | #include "tracker_state.h" | 25 | #include "tracker_state.h" |
| 27 | 26 | ||
| @@ -71,11 +70,12 @@ struct APState { | |||
| 71 | bool sunwarp_shuffle = false; | 70 | bool sunwarp_shuffle = false; |
| 72 | 71 | ||
| 73 | std::map<std::string, std::string> painting_mapping; | 72 | std::map<std::string, std::string> painting_mapping; |
| 73 | std::set<std::string> painting_codomain; | ||
| 74 | std::map<int, SunwarpMapping> sunwarp_mapping; | 74 | std::map<int, SunwarpMapping> sunwarp_mapping; |
| 75 | 75 | ||
| 76 | void Connect(std::string server, std::string player, std::string password) { | 76 | void Connect(std::string server, std::string player, std::string password) { |
| 77 | if (!initialized) { | 77 | if (!initialized) { |
| 78 | TrackerLog("Initializing APState..."); | 78 | wxLogVerbose("Initializing APState..."); |
| 79 | 79 | ||
| 80 | std::thread([this]() { | 80 | std::thread([this]() { |
| 81 | for (;;) { | 81 | for (;;) { |
| @@ -103,15 +103,16 @@ struct APState { | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | tracked_data_storage_keys.push_back("PlayerPos"); | 105 | tracked_data_storage_keys.push_back("PlayerPos"); |
| 106 | tracked_data_storage_keys.push_back("Paintings"); | ||
| 106 | 107 | ||
| 107 | initialized = true; | 108 | initialized = true; |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | tracker_frame->SetStatusMessage("Connecting to Archipelago server...."); | 111 | tracker_frame->SetStatusMessage("Connecting to Archipelago server...."); |
| 111 | TrackerLog("Connecting to Archipelago server (" + server + ")..."); | 112 | wxLogStatus("Connecting to Archipelago server (%s)...", server); |
| 112 | 113 | ||
| 113 | { | 114 | { |
| 114 | TrackerLog("Destroying old AP client..."); | 115 | wxLogVerbose("Destroying old AP client..."); |
| 115 | 116 | ||
| 116 | std::lock_guard client_guard(client_mutex); | 117 | std::lock_guard client_guard(client_mutex); |
| 117 | 118 | ||
| @@ -137,6 +138,7 @@ struct APState { | |||
| 137 | color_shuffle = false; | 138 | color_shuffle = false; |
| 138 | painting_shuffle = false; | 139 | painting_shuffle = false; |
| 139 | painting_mapping.clear(); | 140 | painting_mapping.clear(); |
| 141 | painting_codomain.clear(); | ||
| 140 | mastery_requirement = 21; | 142 | mastery_requirement = 21; |
| 141 | level_2_requirement = 223; | 143 | level_2_requirement = 223; |
| 142 | location_checks = kNORMAL_LOCATIONS; | 144 | location_checks = kNORMAL_LOCATIONS; |
| @@ -155,10 +157,10 @@ struct APState { | |||
| 155 | apclient->set_room_info_handler([this, player, password]() { | 157 | apclient->set_room_info_handler([this, player, password]() { |
| 156 | inventory.clear(); | 158 | inventory.clear(); |
| 157 | 159 | ||
| 158 | TrackerLog("Connected to Archipelago server. Authenticating as " + | 160 | wxLogStatus("Connected to Archipelago server. Authenticating as %s %s", |
| 159 | player + | 161 | player, |
| 160 | (password.empty() ? " without password" | 162 | (password.empty() ? "without password" |
| 161 | : " with password " + password)); | 163 | : "with password " + password)); |
| 162 | tracker_frame->SetStatusMessage( | 164 | tracker_frame->SetStatusMessage( |
| 163 | "Connected to Archipelago server. Authenticating..."); | 165 | "Connected to Archipelago server. Authenticating..."); |
| 164 | 166 | ||
| @@ -170,23 +172,23 @@ struct APState { | |||
| 170 | [this](const std::list<int64_t>& locations) { | 172 | [this](const std::list<int64_t>& locations) { |
| 171 | for (const int64_t location_id : locations) { | 173 | for (const int64_t location_id : locations) { |
| 172 | checked_locations.insert(location_id); | 174 | checked_locations.insert(location_id); |
| 173 | TrackerLog("Location: " + std::to_string(location_id)); | 175 | wxLogVerbose("Location: %lld", location_id); |
| 174 | } | 176 | } |
| 175 | 177 | ||
| 176 | RefreshTracker(); | 178 | RefreshTracker(false); |
| 177 | }); | 179 | }); |
| 178 | 180 | ||
| 179 | apclient->set_slot_disconnected_handler([this]() { | 181 | apclient->set_slot_disconnected_handler([this]() { |
| 180 | tracker_frame->SetStatusMessage( | 182 | tracker_frame->SetStatusMessage( |
| 181 | "Disconnected from Archipelago. Attempting to reconnect..."); | 183 | "Disconnected from Archipelago. Attempting to reconnect..."); |
| 182 | TrackerLog( | 184 | wxLogStatus( |
| 183 | "Slot disconnected from Archipelago. Attempting to reconnect..."); | 185 | "Slot disconnected from Archipelago. Attempting to reconnect..."); |
| 184 | }); | 186 | }); |
| 185 | 187 | ||
| 186 | apclient->set_socket_disconnected_handler([this]() { | 188 | apclient->set_socket_disconnected_handler([this]() { |
| 187 | tracker_frame->SetStatusMessage( | 189 | tracker_frame->SetStatusMessage( |
| 188 | "Disconnected from Archipelago. Attempting to reconnect..."); | 190 | "Disconnected from Archipelago. Attempting to reconnect..."); |
| 189 | TrackerLog( | 191 | wxLogStatus( |
| 190 | "Socket disconnected from Archipelago. Attempting to reconnect..."); | 192 | "Socket disconnected from Archipelago. Attempting to reconnect..."); |
| 191 | }); | 193 | }); |
| 192 | 194 | ||
| @@ -194,10 +196,10 @@ struct APState { | |||
| 194 | [this](const std::list<APClient::NetworkItem>& items) { | 196 | [this](const std::list<APClient::NetworkItem>& items) { |
| 195 | for (const APClient::NetworkItem& item : items) { | 197 | for (const APClient::NetworkItem& item : items) { |
| 196 | inventory[item.item]++; | 198 | inventory[item.item]++; |
| 197 | TrackerLog("Item: " + std::to_string(item.item)); | 199 | wxLogVerbose("Item: %lld", item.item); |
| 198 | } | 200 | } |
| 199 | 201 | ||
| 200 | RefreshTracker(); | 202 | RefreshTracker(false); |
| 201 | }); | 203 | }); |
| 202 | 204 | ||
| 203 | apclient->set_retrieved_handler( | 205 | apclient->set_retrieved_handler( |
| @@ -206,20 +208,20 @@ struct APState { | |||
| 206 | HandleDataStorage(key, value); | 208 | HandleDataStorage(key, value); |
| 207 | } | 209 | } |
| 208 | 210 | ||
| 209 | RefreshTracker(); | 211 | RefreshTracker(false); |
| 210 | }); | 212 | }); |
| 211 | 213 | ||
| 212 | apclient->set_set_reply_handler([this](const std::string& key, | 214 | apclient->set_set_reply_handler([this](const std::string& key, |
| 213 | const nlohmann::json& value, | 215 | const nlohmann::json& value, |
| 214 | const nlohmann::json&) { | 216 | const nlohmann::json&) { |
| 215 | HandleDataStorage(key, value); | 217 | HandleDataStorage(key, value); |
| 216 | RefreshTracker(); | 218 | RefreshTracker(false); |
| 217 | }); | 219 | }); |
| 218 | 220 | ||
| 219 | apclient->set_slot_connected_handler([this]( | 221 | apclient->set_slot_connected_handler([this]( |
| 220 | const nlohmann::json& slot_data) { | 222 | const nlohmann::json& slot_data) { |
| 221 | tracker_frame->SetStatusMessage("Connected to Archipelago!"); | 223 | tracker_frame->SetStatusMessage("Connected to Archipelago!"); |
| 222 | TrackerLog("Connected to Archipelago!"); | 224 | wxLogStatus("Connected to Archipelago!"); |
| 223 | 225 | ||
| 224 | data_storage_prefix = | 226 | data_storage_prefix = |
| 225 | "Lingo_" + std::to_string(apclient->get_player_number()) + "_"; | 227 | "Lingo_" + std::to_string(apclient->get_player_number()) + "_"; |
| @@ -253,6 +255,7 @@ struct APState { | |||
| 253 | for (const auto& mapping_it : | 255 | for (const auto& mapping_it : |
| 254 | slot_data["painting_entrance_to_exit"].items()) { | 256 | slot_data["painting_entrance_to_exit"].items()) { |
| 255 | painting_mapping[mapping_it.key()] = mapping_it.value(); | 257 | painting_mapping[mapping_it.key()] = mapping_it.value(); |
| 258 | painting_codomain.insert(mapping_it.value()); | ||
| 256 | } | 259 | } |
| 257 | } | 260 | } |
| 258 | 261 | ||
| @@ -271,7 +274,8 @@ struct APState { | |||
| 271 | connected = true; | 274 | connected = true; |
| 272 | has_connection_result = true; | 275 | has_connection_result = true; |
| 273 | 276 | ||
| 274 | RefreshTracker(); | 277 | ResetReachabilityRequirements(); |
| 278 | RefreshTracker(true); | ||
| 275 | 279 | ||
| 276 | std::list<std::string> corrected_keys; | 280 | std::list<std::string> corrected_keys; |
| 277 | for (const std::string& key : tracked_data_storage_keys) { | 281 | for (const std::string& key : tracked_data_storage_keys) { |
| @@ -323,7 +327,7 @@ struct APState { | |||
| 323 | } | 327 | } |
| 324 | 328 | ||
| 325 | std::string full_message = hatkirby::implode(error_messages, " "); | 329 | std::string full_message = hatkirby::implode(error_messages, " "); |
| 326 | TrackerLog(full_message); | 330 | wxLogError(wxString(full_message)); |
| 327 | 331 | ||
| 328 | wxMessageBox(full_message, "Connection failed", wxOK | wxICON_ERROR); | 332 | wxMessageBox(full_message, "Connection failed", wxOK | wxICON_ERROR); |
| 329 | }); | 333 | }); |
| @@ -341,8 +345,7 @@ struct APState { | |||
| 341 | DestroyClient(); | 345 | DestroyClient(); |
| 342 | 346 | ||
| 343 | tracker_frame->SetStatusMessage("Disconnected from Archipelago."); | 347 | tracker_frame->SetStatusMessage("Disconnected from Archipelago."); |
| 344 | 348 | wxLogStatus("Timeout while connecting to Archipelago server."); | |
| 345 | TrackerLog("Timeout while connecting to Archipelago server."); | ||
| 346 | wxMessageBox("Timeout while connecting to Archipelago server.", | 349 | wxMessageBox("Timeout while connecting to Archipelago server.", |
| 347 | "Connection failed", wxOK | wxICON_ERROR); | 350 | "Connection failed", wxOK | wxICON_ERROR); |
| 348 | } | 351 | } |
| @@ -353,7 +356,7 @@ struct APState { | |||
| 353 | } | 356 | } |
| 354 | 357 | ||
| 355 | if (connected) { | 358 | if (connected) { |
| 356 | RefreshTracker(); | 359 | RefreshTracker(false); |
| 357 | } else { | 360 | } else { |
| 358 | client_active = false; | 361 | client_active = false; |
| 359 | } | 362 | } |
| @@ -362,12 +365,11 @@ struct APState { | |||
| 362 | void HandleDataStorage(const std::string& key, const nlohmann::json& value) { | 365 | void HandleDataStorage(const std::string& key, const nlohmann::json& value) { |
| 363 | if (value.is_boolean()) { | 366 | if (value.is_boolean()) { |
| 364 | data_storage[key] = value.get<bool>(); | 367 | data_storage[key] = value.get<bool>(); |
| 365 | TrackerLog("Data storage " + key + " retrieved as " + | 368 | wxLogVerbose("Data storage %s retrieved as %s", key, |
| 366 | (value.get<bool>() ? "true" : "false")); | 369 | (value.get<bool>() ? "true" : "false")); |
| 367 | } else if (value.is_number()) { | 370 | } else if (value.is_number()) { |
| 368 | data_storage[key] = value.get<int>(); | 371 | data_storage[key] = value.get<int>(); |
| 369 | TrackerLog("Data storage " + key + " retrieved as " + | 372 | wxLogVerbose("Data storage %s retrieved as %d", key, value.get<int>()); |
| 370 | std::to_string(value.get<int>())); | ||
| 371 | } else if (value.is_object()) { | 373 | } else if (value.is_object()) { |
| 372 | if (key.ends_with("PlayerPos")) { | 374 | if (key.ends_with("PlayerPos")) { |
| 373 | auto map_value = value.get<std::map<std::string, int>>(); | 375 | auto map_value = value.get<std::map<std::string, int>>(); |
| @@ -376,7 +378,7 @@ struct APState { | |||
| 376 | data_storage[key] = value.get<std::map<std::string, int>>(); | 378 | data_storage[key] = value.get<std::map<std::string, int>>(); |
| 377 | } | 379 | } |
| 378 | 380 | ||
| 379 | TrackerLog("Data storage " + key + " retrieved as dictionary"); | 381 | wxLogVerbose("Data storage %s retrieved as dictionary", key); |
| 380 | } else if (value.is_null()) { | 382 | } else if (value.is_null()) { |
| 381 | if (key.ends_with("PlayerPos")) { | 383 | if (key.ends_with("PlayerPos")) { |
| 382 | player_pos = std::nullopt; | 384 | player_pos = std::nullopt; |
| @@ -384,7 +386,19 @@ struct APState { | |||
| 384 | data_storage.erase(key); | 386 | data_storage.erase(key); |
| 385 | } | 387 | } |
| 386 | 388 | ||
| 387 | TrackerLog("Data storage " + key + " retrieved as null"); | 389 | wxLogVerbose("Data storage %s retrieved as null", key); |
| 390 | } else if (value.is_array()) { | ||
| 391 | auto list_value = value.get<std::vector<std::string>>(); | ||
| 392 | |||
| 393 | if (key.ends_with("Paintings")) { | ||
| 394 | data_storage[key] = | ||
| 395 | std::set<std::string>(list_value.begin(), list_value.end()); | ||
| 396 | } else { | ||
| 397 | data_storage[key] = list_value; | ||
| 398 | } | ||
| 399 | |||
| 400 | wxLogVerbose("Data storage %s retrieved as list: [%s]", key, | ||
| 401 | hatkirby::implode(list_value, ", ")); | ||
| 388 | } | 402 | } |
| 389 | } | 403 | } |
| 390 | 404 | ||
| @@ -407,22 +421,46 @@ struct APState { | |||
| 407 | return data_storage.count(key) && std::any_cast<bool>(data_storage.at(key)); | 421 | return data_storage.count(key) && std::any_cast<bool>(data_storage.at(key)); |
| 408 | } | 422 | } |
| 409 | 423 | ||
| 410 | void RefreshTracker() { | 424 | const std::set<std::string>& GetCheckedPaintings() { |
| 411 | TrackerLog("Refreshing display..."); | 425 | std::string key = data_storage_prefix + "Paintings"; |
| 426 | if (!data_storage.count(key)) { | ||
| 427 | data_storage[key] = std::set<std::string>(); | ||
| 428 | } | ||
| 429 | |||
| 430 | return std::any_cast<const std::set<std::string>&>(data_storage.at(key)); | ||
| 431 | } | ||
| 432 | |||
| 433 | bool IsPaintingChecked(const std::string& painting_id) { | ||
| 434 | const auto& checked_paintings = GetCheckedPaintings(); | ||
| 435 | |||
| 436 | return checked_paintings.count(painting_id) || | ||
| 437 | (painting_mapping.count(painting_id) && | ||
| 438 | checked_paintings.count(painting_mapping.at(painting_id))); | ||
| 439 | } | ||
| 440 | |||
| 441 | void RefreshTracker(bool reset) { | ||
| 442 | wxLogVerbose("Refreshing display..."); | ||
| 412 | 443 | ||
| 413 | RecalculateReachability(); | 444 | RecalculateReachability(); |
| 414 | tracker_frame->UpdateIndicators(); | 445 | |
| 446 | if (reset) { | ||
| 447 | tracker_frame->ResetIndicators(); | ||
| 448 | } else { | ||
| 449 | tracker_frame->UpdateIndicators(); | ||
| 450 | } | ||
| 415 | } | 451 | } |
| 416 | 452 | ||
| 417 | int64_t GetItemId(const std::string& item_name) { | 453 | int64_t GetItemId(const std::string& item_name) { |
| 418 | int64_t ap_id = apclient->get_item_id(item_name); | 454 | int64_t ap_id = apclient->get_item_id(item_name); |
| 419 | if (ap_id == APClient::INVALID_NAME_ID) { | 455 | if (ap_id == APClient::INVALID_NAME_ID) { |
| 420 | TrackerLog("Could not find AP item ID for " + item_name); | 456 | wxLogError("Could not find AP item ID for %s", item_name); |
| 421 | } | 457 | } |
| 422 | 458 | ||
| 423 | return ap_id; | 459 | return ap_id; |
| 424 | } | 460 | } |
| 425 | 461 | ||
| 462 | std::string GetItemName(int id) { return apclient->get_item_name(id); } | ||
| 463 | |||
| 426 | bool HasReachedGoal() { | 464 | bool HasReachedGoal() { |
| 427 | return data_storage.count(victory_data_storage_key) && | 465 | return data_storage.count(victory_data_storage_key) && |
| 428 | std::any_cast<int>(data_storage.at(victory_data_storage_key)) == | 466 | std::any_cast<int>(data_storage.at(victory_data_storage_key)) == |
| @@ -461,16 +499,32 @@ bool AP_HasItem(int item_id, int quantity) { | |||
| 461 | return GetState().HasItem(item_id, quantity); | 499 | return GetState().HasItem(item_id, quantity); |
| 462 | } | 500 | } |
| 463 | 501 | ||
| 502 | std::string AP_GetItemName(int item_id) { | ||
| 503 | return GetState().GetItemName(item_id); | ||
| 504 | } | ||
| 505 | |||
| 464 | DoorShuffleMode AP_GetDoorShuffleMode() { return GetState().door_shuffle_mode; } | 506 | DoorShuffleMode AP_GetDoorShuffleMode() { return GetState().door_shuffle_mode; } |
| 465 | 507 | ||
| 466 | bool AP_IsColorShuffle() { return GetState().color_shuffle; } | 508 | bool AP_IsColorShuffle() { return GetState().color_shuffle; } |
| 467 | 509 | ||
| 468 | bool AP_IsPaintingShuffle() { return GetState().painting_shuffle; } | 510 | bool AP_IsPaintingShuffle() { return GetState().painting_shuffle; } |
| 469 | 511 | ||
| 470 | const std::map<std::string, std::string> AP_GetPaintingMapping() { | 512 | const std::map<std::string, std::string>& AP_GetPaintingMapping() { |
| 471 | return GetState().painting_mapping; | 513 | return GetState().painting_mapping; |
| 472 | } | 514 | } |
| 473 | 515 | ||
| 516 | bool AP_IsPaintingMappedTo(const std::string& painting_id) { | ||
| 517 | return GetState().painting_codomain.count(painting_id); | ||
| 518 | } | ||
| 519 | |||
| 520 | const std::set<std::string>& AP_GetCheckedPaintings() { | ||
| 521 | return GetState().GetCheckedPaintings(); | ||
| 522 | } | ||
| 523 | |||
| 524 | bool AP_IsPaintingChecked(const std::string& painting_id) { | ||
| 525 | return GetState().IsPaintingChecked(painting_id); | ||
| 526 | } | ||
| 527 | |||
| 474 | int AP_GetMasteryRequirement() { return GetState().mastery_requirement; } | 528 | int AP_GetMasteryRequirement() { return GetState().mastery_requirement; } |
| 475 | 529 | ||
| 476 | int AP_GetLevel2Requirement() { return GetState().level_2_requirement; } | 530 | int AP_GetLevel2Requirement() { return GetState().level_2_requirement; } |
