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; } |