From 325ea53e7bb873870b46d3e38b2b314493a22f79 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Wed, 3 May 2023 18:27:37 -0400 Subject: Refactored APState It is no longer a class, because it didn't need to be. --- ap_state.cpp | 245 +++++++++++++++++++++++++++++++----------------------- ap_state.h | 66 +++------------ area_popup.cpp | 2 +- tracker_frame.cpp | 9 +- tracker_panel.cpp | 27 +++--- tracker_state.cpp | 24 +++--- 6 files changed, 185 insertions(+), 188 deletions(-) diff --git a/ap_state.cpp b/ap_state.cpp index 8b7339a..c13b87c 100644 --- a/ap_state.cpp +++ b/ap_state.cpp @@ -11,9 +11,14 @@ #include #include #include +#include +#include +#include #include +#include #include "game_data.h" +#include "tracker_frame.h" #include "tracker_state.h" constexpr int AP_MAJOR = 0; @@ -22,29 +27,81 @@ constexpr int AP_REVISION = 0; constexpr int ITEM_HANDLING = 7; // <- all -static APClient* apclient = nullptr; +namespace { -APState::APState() { - std::thread([this]() { - for (;;) { - { - std::lock_guard client_guard(client_mutex_); - if (apclient) { - apclient->poll(); +APClient* apclient = nullptr; + +bool initialized = false; + +TrackerFrame* tracker_frame; + +bool client_active = false; +std::mutex client_mutex; + +bool connected = false; +bool has_connection_result = false; + +std::map inventory; +std::set checked_locations; + +std::map, int64_t> ap_id_by_location_id; +std::map ap_id_by_item_name; +std::map ap_id_by_color; +std::map progressive_item_by_ap_id; + +DoorShuffleMode door_shuffle_mode = kNO_DOORS; +bool color_shuffle = false; +bool painting_shuffle = false; + +std::map painting_mapping; + +void RefreshTracker() { + GetTrackerState().CalculateState(); + tracker_frame->UpdateIndicators(); +} + +int64_t GetItemId(const std::string& item_name) { + int64_t ap_id = apclient->get_item_id(item_name); + if (ap_id == APClient::INVALID_NAME_ID) { + std::cout << "Could not find AP item ID for " << item_name << std::endl; + } + + return ap_id; +} + +void DestroyClient() { + client_active = false; + apclient->reset(); + delete apclient; + apclient = nullptr; +} + +} // namespace + +void AP_SetTrackerFrame(TrackerFrame* arg) { tracker_frame = arg; } + +void AP_Connect(std::string server, std::string player, std::string password) { + if (!initialized) { + std::thread([]() { + for (;;) { + { + std::lock_guard client_guard(client_mutex); + if (apclient) { + apclient->poll(); + } } + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } + }).detach(); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - }).detach(); -} + initialized = true; + } -void APState::Connect(std::string server, std::string player, - std::string password) { - tracker_frame_->SetStatusMessage("Connecting to Archipelago server...."); + tracker_frame->SetStatusMessage("Connecting to Archipelago server...."); { - std::lock_guard client_guard(client_mutex_); + std::lock_guard client_guard(client_mutex); if (apclient) { DestroyClient(); @@ -53,20 +110,20 @@ void APState::Connect(std::string server, std::string player, apclient = new APClient(ap_get_uuid(""), "Lingo", server); } - inventory_.clear(); - checked_locations_.clear(); - door_shuffle_mode_ = kNO_DOORS; - color_shuffle_ = false; - painting_shuffle_ = false; - painting_mapping_.clear(); + inventory.clear(); + checked_locations.clear(); + door_shuffle_mode = kNO_DOORS; + color_shuffle = false; + painting_shuffle = false; + painting_mapping.clear(); - connected_ = false; - has_connection_result_ = false; + connected = false; + has_connection_result = false; - apclient->set_room_info_handler([this, player, password]() { - inventory_.clear(); + apclient->set_room_info_handler([player, password]() { + inventory.clear(); - tracker_frame_->SetStatusMessage( + tracker_frame->SetStatusMessage( "Connected to Archipelago server. Authenticating..."); apclient->ConnectSlot(player, password, ITEM_HANDLING, {"Tracker"}, @@ -74,61 +131,60 @@ void APState::Connect(std::string server, std::string player, }); apclient->set_location_checked_handler( - [this](const std::list& locations) { + [](const std::list& locations) { for (const int64_t location_id : locations) { - checked_locations_.insert(location_id); + checked_locations.insert(location_id); std::cout << "Location: " << location_id << std::endl; } RefreshTracker(); }); - apclient->set_slot_disconnected_handler([this]() { - tracker_frame_->SetStatusMessage( + apclient->set_slot_disconnected_handler([]() { + tracker_frame->SetStatusMessage( "Disconnected from Archipelago. Attempting to reconnect..."); }); - apclient->set_socket_disconnected_handler([this]() { - tracker_frame_->SetStatusMessage( + apclient->set_socket_disconnected_handler([]() { + tracker_frame->SetStatusMessage( "Disconnected from Archipelago. Attempting to reconnect..."); }); apclient->set_items_received_handler( - [this](const std::list& items) { + [](const std::list& items) { for (const APClient::NetworkItem& item : items) { - inventory_[item.item]++; + inventory[item.item]++; std::cout << "Item: " << item.item << std::endl; } RefreshTracker(); }); - apclient->set_slot_connected_handler([this](const nlohmann::json& slot_data) { - tracker_frame_->SetStatusMessage("Connected to Archipelago!"); + apclient->set_slot_connected_handler([](const nlohmann::json& slot_data) { + tracker_frame->SetStatusMessage("Connected to Archipelago!"); - door_shuffle_mode_ = slot_data["shuffle_doors"].get(); - color_shuffle_ = slot_data["shuffle_colors"].get(); - painting_shuffle_ = slot_data["shuffle_paintings"].get(); + door_shuffle_mode = slot_data["shuffle_doors"].get(); + color_shuffle = slot_data["shuffle_colors"].get(); + painting_shuffle = slot_data["shuffle_paintings"].get(); - if (painting_shuffle_ && slot_data.contains("painting_entrance_to_exit")) { - painting_mapping_.clear(); + if (painting_shuffle && slot_data.contains("painting_entrance_to_exit")) { + painting_mapping.clear(); for (const auto& mapping_it : slot_data["painting_entrance_to_exit"].items()) { - painting_mapping_[mapping_it.key()] = mapping_it.value(); + painting_mapping[mapping_it.key()] = mapping_it.value(); } } - connected_ = true; - has_connection_result_ = true; + connected = true; + has_connection_result = true; }); - apclient->set_slot_refused_handler([this]( - const std::list& errors) { - connected_ = false; - has_connection_result_ = true; + apclient->set_slot_refused_handler([](const std::list& errors) { + connected = false; + has_connection_result = true; - tracker_frame_->SetStatusMessage("Disconnected from Archipelago."); + tracker_frame->SetStatusMessage("Disconnected from Archipelago."); std::vector error_messages; error_messages.push_back("Could not connect to Archipelago."); @@ -158,19 +214,19 @@ void APState::Connect(std::string server, std::string player, wxMessageBox(full_message, "Connection failed", wxOK | wxICON_ERROR); }); - client_active_ = true; + client_active = true; int timeout = 5000; // 5 seconds int interval = 100; int remaining_loops = timeout / interval; - while (!has_connection_result_) { + while (!has_connection_result) { if (interval == 0) { - connected_ = false; - has_connection_result_ = true; + connected = false; + has_connection_result = true; DestroyClient(); - tracker_frame_->SetStatusMessage("Disconnected from Archipelago."); + tracker_frame->SetStatusMessage("Disconnected from Archipelago."); wxMessageBox("Timeout while connecting to Archipelago server.", "Connection failed", wxOK | wxICON_ERROR); @@ -181,7 +237,7 @@ void APState::Connect(std::string server, std::string player, interval--; } - if (connected_) { + if (connected) { for (const MapArea& map_area : GetGameData().GetMapAreas()) { for (int section_id = 0; section_id < map_area.locations.size(); section_id++) { @@ -192,91 +248,76 @@ void APState::Connect(std::string server, std::string player, std::cout << "Could not find AP location ID for " << location.ap_location_name << std::endl; } else { - ap_id_by_location_id_[{map_area.id, section_id}] = ap_id; + ap_id_by_location_id[{map_area.id, section_id}] = ap_id; } } } for (const Door& door : GetGameData().GetDoors()) { if (!door.skip_item) { - ap_id_by_item_name_[door.item_name] = GetItemId(door.item_name); + ap_id_by_item_name[door.item_name] = GetItemId(door.item_name); if (!door.group_name.empty() && - !ap_id_by_item_name_.count(door.group_name)) { - ap_id_by_item_name_[door.group_name] = GetItemId(door.group_name); + !ap_id_by_item_name.count(door.group_name)) { + ap_id_by_item_name[door.group_name] = GetItemId(door.group_name); } for (const ProgressiveRequirement& prog_req : door.progressives) { - ap_id_by_item_name_[prog_req.item_name] = GetItemId(prog_req.item_name); + ap_id_by_item_name[prog_req.item_name] = + GetItemId(prog_req.item_name); } } } - ap_id_by_color_[LingoColor::kBlack] = GetItemId("Black"); - ap_id_by_color_[LingoColor::kRed] = GetItemId("Red"); - ap_id_by_color_[LingoColor::kBlue] = GetItemId("Blue"); - ap_id_by_color_[LingoColor::kYellow] = GetItemId("Yellow"); - ap_id_by_color_[LingoColor::kPurple] = GetItemId("Purple"); - ap_id_by_color_[LingoColor::kOrange] = GetItemId("Orange"); - ap_id_by_color_[LingoColor::kGreen] = GetItemId("Green"); - ap_id_by_color_[LingoColor::kBrown] = GetItemId("Brown"); - ap_id_by_color_[LingoColor::kGray] = GetItemId("Gray"); + ap_id_by_color[LingoColor::kBlack] = GetItemId("Black"); + ap_id_by_color[LingoColor::kRed] = GetItemId("Red"); + ap_id_by_color[LingoColor::kBlue] = GetItemId("Blue"); + ap_id_by_color[LingoColor::kYellow] = GetItemId("Yellow"); + ap_id_by_color[LingoColor::kPurple] = GetItemId("Purple"); + ap_id_by_color[LingoColor::kOrange] = GetItemId("Orange"); + ap_id_by_color[LingoColor::kGreen] = GetItemId("Green"); + ap_id_by_color[LingoColor::kBrown] = GetItemId("Brown"); + ap_id_by_color[LingoColor::kGray] = GetItemId("Gray"); RefreshTracker(); } else { - client_active_ = false; + client_active = false; } } -bool APState::HasCheckedGameLocation(int area_id, int section_id) const { +bool AP_HasCheckedGameLocation(int area_id, int section_id) { std::tuple location_key = {area_id, section_id}; - if (ap_id_by_location_id_.count(location_key)) { - return checked_locations_.count(ap_id_by_location_id_.at(location_key)); + if (ap_id_by_location_id.count(location_key)) { + return checked_locations.count(ap_id_by_location_id.at(location_key)); } else { return false; } } -bool APState::HasColorItem(LingoColor color) const { - if (ap_id_by_color_.count(color)) { - return inventory_.count(ap_id_by_color_.at(color)); +bool AP_HasColorItem(LingoColor color) { + if (ap_id_by_color.count(color)) { + return inventory.count(ap_id_by_color.at(color)); } else { return false; } } -bool APState::HasItem(const std::string& item, int quantity) const { - if (ap_id_by_item_name_.count(item)) { - int64_t ap_id = ap_id_by_item_name_.at(item); - return inventory_.count(ap_id) && inventory_.at(ap_id) >= quantity; +bool AP_HasItem(const std::string& item, int quantity) { + if (ap_id_by_item_name.count(item)) { + int64_t ap_id = ap_id_by_item_name.at(item); + return inventory.count(ap_id) && inventory.at(ap_id) >= quantity; } else { return false; } } -void APState::RefreshTracker() { - GetTrackerState().CalculateState(); - tracker_frame_->UpdateIndicators(); -} - -int64_t APState::GetItemId(const std::string& item_name) { - int64_t ap_id = apclient->get_item_id(item_name); - if (ap_id == APClient::INVALID_NAME_ID) { - std::cout << "Could not find AP item ID for " << item_name << std::endl; - } +DoorShuffleMode AP_GetDoorShuffleMode() { return door_shuffle_mode; } - return ap_id; -} +bool AP_IsColorShuffle() { return color_shuffle; } -void APState::DestroyClient() { - client_active_ = false; - apclient->reset(); - delete apclient; - apclient = nullptr; -} +bool AP_IsPaintingShuffle() { return painting_shuffle; } -APState& GetAPState() { - static APState* instance = new APState(); - return *instance; +const std::map AP_GetPaintingMapping() { + return painting_mapping; } diff --git a/ap_state.h b/ap_state.h index ce73528..434b7b2 100644 --- a/ap_state.h +++ b/ap_state.h @@ -1,73 +1,31 @@ #ifndef AP_STATE_H_664A4180 #define AP_STATE_H_664A4180 -#include -#include -#include +#include #include -#include #include "game_data.h" -#include "tracker_frame.h" -enum DoorShuffleMode { kNO_DOORS = 0, kSIMPLE_DOORS = 1, kCOMPLEX_DOORS = 2 }; - -class APState { - public: - APState(); - - void SetTrackerFrame(TrackerFrame* tracker_frame) { - tracker_frame_ = tracker_frame; - } - - void Connect(std::string server, std::string player, std::string password); - - bool HasCheckedGameLocation(int area_id, int section_id) const; - - bool HasColorItem(LingoColor color) const; - - bool HasItem(const std::string& item, int quantity = 1) const; +class TrackerFrame; - DoorShuffleMode GetDoorShuffleMode() const { return door_shuffle_mode_; } - - bool IsColorShuffle() const { return color_shuffle_; } - - bool IsPaintingShuffle() const { return painting_shuffle_; } - - const std::map GetPaintingMapping() const { - return painting_mapping_; - } - - private: - void RefreshTracker(); - - int64_t GetItemId(const std::string& item_name); +enum DoorShuffleMode { kNO_DOORS = 0, kSIMPLE_DOORS = 1, kCOMPLEX_DOORS = 2 }; - void DestroyClient(); +void AP_SetTrackerFrame(TrackerFrame* tracker_frame); - TrackerFrame* tracker_frame_; +void AP_Connect(std::string server, std::string player, std::string password); - bool client_active_ = false; - std::mutex client_mutex_; +bool AP_HasCheckedGameLocation(int area_id, int section_id); - bool connected_ = false; - bool has_connection_result_ = false; +bool AP_HasColorItem(LingoColor color); - std::map inventory_; - std::set checked_locations_; +bool AP_HasItem(const std::string& item, int quantity = 1); - std::map, int64_t> ap_id_by_location_id_; - std::map ap_id_by_item_name_; - std::map ap_id_by_color_; - std::map progressive_item_by_ap_id_; +DoorShuffleMode AP_GetDoorShuffleMode(); - DoorShuffleMode door_shuffle_mode_ = kNO_DOORS; - bool color_shuffle_ = false; - bool painting_shuffle_ = false; +bool AP_IsColorShuffle(); - std::map painting_mapping_; -}; +bool AP_IsPaintingShuffle(); -APState& GetAPState(); +const std::map AP_GetPaintingMapping(); #endif /* end of include guard: AP_STATE_H_664A4180 */ diff --git a/area_popup.cpp b/area_popup.cpp index 4cc3c63..a8ff612 100644 --- a/area_popup.cpp +++ b/area_popup.cpp @@ -43,7 +43,7 @@ void AreaPopup::UpdateIndicators() { const MapArea& map_area = GetGameData().GetMapArea(area_id_); for (int section_id = 0; section_id < map_area.locations.size(); section_id++) { - bool checked = GetAPState().HasCheckedGameLocation(area_id_, section_id); + bool checked = AP_HasCheckedGameLocation(area_id_, section_id); bool reachable = GetTrackerState().IsLocationReachable(area_id_, section_id); const wxColour* text_color = reachable ? wxWHITE : wxRED; diff --git a/tracker_frame.cpp b/tracker_frame.cpp index 774b710..2a862a5 100644 --- a/tracker_frame.cpp +++ b/tracker_frame.cpp @@ -11,10 +11,11 @@ wxDEFINE_EVENT(STATE_CHANGED, wxCommandEvent); wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent); TrackerFrame::TrackerFrame() - : wxFrame(nullptr, wxID_ANY, "Lingo Archipelago Tracker", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE) { + : wxFrame(nullptr, wxID_ANY, "Lingo Archipelago Tracker", wxDefaultPosition, + wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE) { ::wxInitAllImageHandlers(); - GetAPState().SetTrackerFrame(this); + AP_SetTrackerFrame(this); SetSize(1280, 728); @@ -70,8 +71,8 @@ void TrackerFrame::OnConnect(wxCommandEvent &event) { GetTrackerConfig().ap_password = dlg.GetPasswordValue(); GetTrackerConfig().Save(); - GetAPState().Connect(dlg.GetServerValue(), dlg.GetPlayerValue(), - dlg.GetPasswordValue()); + AP_Connect(dlg.GetServerValue(), dlg.GetPlayerValue(), + dlg.GetPasswordValue()); } } diff --git a/tracker_panel.cpp b/tracker_panel.cpp index 73cac41..0e0569b 100644 --- a/tracker_panel.cpp +++ b/tracker_panel.cpp @@ -21,7 +21,7 @@ TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { area.popup = new AreaPopup(this, map_area.id); area.popup->SetPosition({0, 0}); - + areas_.push_back(area); } @@ -34,7 +34,7 @@ TrackerPanel::TrackerPanel(wxWindow *parent) : wxPanel(parent, wxID_ANY) { void TrackerPanel::UpdateIndicators() { Redraw(); - for (AreaIndicator& area : areas_) { + for (AreaIndicator &area : areas_) { area.popup->UpdateIndicators(); } } @@ -90,7 +90,7 @@ void TrackerPanel::Redraw() { wxMemoryDC dc; dc.SelectObject(rendered_); - for (AreaIndicator& area : areas_) { + for (AreaIndicator &area : areas_) { const wxBrush *brush_color = wxGREY_BRUSH; const MapArea &map_area = GetGameData().GetMapArea(area.area_id); @@ -98,10 +98,8 @@ void TrackerPanel::Redraw() { bool has_unreachable_unchecked = false; for (int section_id = 0; section_id < map_area.locations.size(); section_id++) { - if (!GetAPState().HasCheckedGameLocation(area.area_id, - section_id)) { - if (GetTrackerState().IsLocationReachable(area.area_id, - section_id)) { + if (!AP_HasCheckedGameLocation(area.area_id, section_id)) { + if (GetTrackerState().IsLocationReachable(area.area_id, section_id)) { has_reachable_unchecked = true; } else { has_unreachable_unchecked = true; @@ -121,16 +119,15 @@ void TrackerPanel::Redraw() { final_width * AREA_EFFECTIVE_SIZE / image_size.GetWidth(); int actual_border_size = real_area_size * AREA_BORDER_SIZE / AREA_EFFECTIVE_SIZE; - int real_area_x = - final_x + (map_area.map_x - (AREA_EFFECTIVE_SIZE / 2)) * - final_width / image_size.GetWidth(); - int real_area_y = - final_y + (map_area.map_y - (AREA_EFFECTIVE_SIZE / 2)) * - final_width / image_size.GetWidth(); - + int real_area_x = final_x + (map_area.map_x - (AREA_EFFECTIVE_SIZE / 2)) * + final_width / image_size.GetWidth(); + int real_area_y = final_y + (map_area.map_y - (AREA_EFFECTIVE_SIZE / 2)) * + final_width / image_size.GetWidth(); + dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size)); dc.SetBrush(*brush_color); - dc.DrawRectangle({real_area_x, real_area_y}, {real_area_size, real_area_size}); + dc.DrawRectangle({real_area_x, real_area_y}, + {real_area_size, real_area_size}); area.real_x1 = real_area_x; area.real_x2 = real_area_x + real_area_size; diff --git a/tracker_state.cpp b/tracker_state.cpp index 4921d3f..6eaf87a 100644 --- a/tracker_state.cpp +++ b/tracker_state.cpp @@ -28,9 +28,9 @@ bool IsPanelReachable_Helper(int panel_id, } } - if (GetAPState().IsColorShuffle()) { + if (AP_IsColorShuffle()) { for (LingoColor color : panel_obj.colors) { - if (!GetAPState().HasColorItem(color)) { + if (!AP_HasColorItem(color)) { return false; } } @@ -42,7 +42,7 @@ bool IsPanelReachable_Helper(int panel_id, bool IsDoorReachable_Helper(int door_id, const std::set& reachable_rooms) { const Door& door_obj = GetGameData().GetDoor(door_id); - if (GetAPState().GetDoorShuffleMode() == kNO_DOORS || door_obj.skip_item) { + if (AP_GetDoorShuffleMode() == kNO_DOORS || door_obj.skip_item) { if (!reachable_rooms.count(door_obj.room)) { return false; } @@ -54,15 +54,15 @@ bool IsDoorReachable_Helper(int door_id, const std::set& reachable_rooms) { } return true; - } else if (GetAPState().GetDoorShuffleMode() == kSIMPLE_DOORS && + } else if (AP_GetDoorShuffleMode() == kSIMPLE_DOORS && !door_obj.group_name.empty()) { - return GetAPState().HasItem(door_obj.group_name); + return AP_HasItem(door_obj.group_name); } else { - bool has_item = GetAPState().HasItem(door_obj.item_name); + bool has_item = AP_HasItem(door_obj.item_name); if (!has_item) { for (const ProgressiveRequirement& prog_req : door_obj.progressives) { - if (GetAPState().HasItem(prog_req.item_name, prog_req.quantity)) { + if (AP_HasItem(prog_req.item_name, prog_req.quantity)) { has_item = true; break; } @@ -96,7 +96,7 @@ void TrackerState::CalculateState() { if (room_exit.door.has_value()) { if (IsDoorReachable_Helper(*room_exit.door, reachable_rooms)) { valid_transition = true; - } else if (GetAPState().GetDoorShuffleMode() == kNO_DOORS) { + } else if (AP_GetDoorShuffleMode() == kNO_DOORS) { new_boundary.push_back(room_exit); } } else { @@ -110,17 +110,17 @@ void TrackerState::CalculateState() { const Room& room_obj = GetGameData().GetRoom(room_exit.destination_room); for (const Exit& out_edge : room_obj.exits) { - if (!out_edge.painting || !GetAPState().IsPaintingShuffle()) { + if (!out_edge.painting || !AP_IsPaintingShuffle()) { new_boundary.push_back(out_edge); } } - if (GetAPState().IsPaintingShuffle()) { + if (AP_IsPaintingShuffle()) { for (const PaintingExit& out_edge : room_obj.paintings) { - if (GetAPState().GetPaintingMapping().count(out_edge.id)) { + if (AP_GetPaintingMapping().count(out_edge.id)) { Exit painting_exit; painting_exit.destination_room = GetGameData().GetRoomForPainting( - GetAPState().GetPaintingMapping().at(out_edge.id)); + AP_GetPaintingMapping().at(out_edge.id)); painting_exit.door = out_edge.door; new_boundary.push_back(painting_exit); -- cgit 1.4.1