about summary refs log tree commit diff stats
path: root/src/ap_state.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ap_state.cpp')
-rw-r--r--src/ap_state.cpp120
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
502std::string AP_GetItemName(int item_id) {
503 return GetState().GetItemName(item_id);
504}
505
464DoorShuffleMode AP_GetDoorShuffleMode() { return GetState().door_shuffle_mode; } 506DoorShuffleMode AP_GetDoorShuffleMode() { return GetState().door_shuffle_mode; }
465 507
466bool AP_IsColorShuffle() { return GetState().color_shuffle; } 508bool AP_IsColorShuffle() { return GetState().color_shuffle; }
467 509
468bool AP_IsPaintingShuffle() { return GetState().painting_shuffle; } 510bool AP_IsPaintingShuffle() { return GetState().painting_shuffle; }
469 511
470const std::map<std::string, std::string> AP_GetPaintingMapping() { 512const std::map<std::string, std::string>& AP_GetPaintingMapping() {
471 return GetState().painting_mapping; 513 return GetState().painting_mapping;
472} 514}
473 515
516bool AP_IsPaintingMappedTo(const std::string& painting_id) {
517 return GetState().painting_codomain.count(painting_id);
518}
519
520const std::set<std::string>& AP_GetCheckedPaintings() {
521 return GetState().GetCheckedPaintings();
522}
523
524bool AP_IsPaintingChecked(const std::string& painting_id) {
525 return GetState().IsPaintingChecked(painting_id);
526}
527
474int AP_GetMasteryRequirement() { return GetState().mastery_requirement; } 528int AP_GetMasteryRequirement() { return GetState().mastery_requirement; }
475 529
476int AP_GetLevel2Requirement() { return GetState().level_2_requirement; } 530int AP_GetLevel2Requirement() { return GetState().level_2_requirement; }