From 704c08bb439b9a90f7be2d26a0c8b01777e2cf2c Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Tue, 2 May 2023 00:24:09 -0400 Subject: Started reading in game data yaml --- .gitignore | 1 + .gitmodules | 3 + CMakeLists.txt | 11 ++- game_data.cpp | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ game_data.h | 86 +++++++++++++++++++ vendor/hkutil | 1 + 6 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 100644 game_data.cpp create mode 100644 game_data.h create mode 160000 vendor/hkutil diff --git a/.gitignore b/.gitignore index 567609b..4a87eed 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build/ +assets/LL1.yaml diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5438989 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vendor/hkutil"] + path = vendor/hkutil + url = https://github.com/hatkirby/hkutil.git diff --git a/CMakeLists.txt b/CMakeLists.txt index cb5cf25..2e4ece5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,11 +6,20 @@ set(CMAKE_BUILD_TYPE Debug) find_package(wxWidgets COMPONENTS core base) include(${wxWidgets_USE_FILE}) +find_package(PkgConfig) +pkg_check_modules(yaml-cpp yaml-cpp REQUIRED) + +include_directories( + vendor/hkutil + ${yaml-cpp_INCLUDE_DIRS} +) + add_executable(lingo_ap_tracker main.cpp tracker_frame.cpp tracker_panel.cpp + game_data.cpp ) set_property(TARGET lingo_ap_tracker PROPERTY CXX_STANDARD 17) set_property(TARGET lingo_ap_tracker PROPERTY CXX_STANDARD_REQUIRED ON) -target_link_libraries(lingo_ap_tracker ${wxWidgets_LIBRARIES}) +target_link_libraries(lingo_ap_tracker ${wxWidgets_LIBRARIES} ${yaml-cpp_LIBRARIES}) diff --git a/game_data.cpp b/game_data.cpp new file mode 100644 index 0000000..db574d3 --- /dev/null +++ b/game_data.cpp @@ -0,0 +1,255 @@ +#include "game_data.h" + +#include +#include +#include + +LingoColor GetColorForString(const std::string &str) { + if (str == "black") { + return LingoColor::kBlack; + } else if (str == "red") { + return LingoColor::kRed; + } else if (str == "blue") { + return LingoColor::kBlue; + } else if (str == "yellow") { + return LingoColor::kYellow; + } else if (str == "orange") { + return LingoColor::kOrange; + } else if (str == "green") { + return LingoColor::kGreen; + } else if (str == "gray") { + return LingoColor::kGray; + } else if (str == "brown") { + return LingoColor::kBrown; + } else if (str == "purple") { + return LingoColor::kPurple; + } else { + std::cout << "Invalid color: " << str << std::endl; + return LingoColor::kNone; + } +} + +GameData::GameData() { + YAML::Node lingo_config = YAML::LoadFile("assets/LL1.yaml"); + YAML::Node areas_config = YAML::LoadFile("assets/areas.yaml"); + + rooms_.reserve(lingo_config.size() + 1); // The +1 is for Menu + + for (const auto &room_it : lingo_config) { + int room_id = AddOrGetRoom(room_it.first.as()); + Room &room_obj = rooms_[room_id]; + + for (const auto &entrance_it : room_it.second["entrances"]) { + int from_room_id = AddOrGetRoom(entrance_it.first.as()); + Room &from_room_obj = rooms_[from_room_id]; + + switch (entrance_it.second.Type()) { + case YAML::NodeType::Scalar: { + // This is just "true". + from_room_obj.exits.push_back({.destination_room = room_id}); + break; + } + case YAML::NodeType::Map: { + Exit exit_obj; + exit_obj.destination_room = room_id; + + if (entrance_it.second["door"]) { + std::string door_room = room_obj.name; + if (entrance_it.second["room"]) { + door_room = entrance_it.second["room"].as(); + } + exit_obj.door = AddOrGetDoor( + door_room, entrance_it.second["door"].as()); + } + + from_room_obj.exits.push_back(exit_obj); + break; + } + case YAML::NodeType::Sequence: { + for (const auto &option : entrance_it.second) { + Exit exit_obj; + exit_obj.destination_room = room_id; + + std::string door_room = room_obj.name; + if (option["room"]) { + door_room = option["room"].as(); + } + exit_obj.door = + AddOrGetDoor(door_room, option["door"].as()); + + from_room_obj.exits.push_back(exit_obj); + } + + break; + } + default: { + // This shouldn't happen. + std::cout << "Error reading game data: " << entrance_it << std::endl; + break; + } + } + } + + if (room_it.second["panels"]) { + for (const auto &panel_it : room_it.second["panels"]) { + int panel_id = + AddOrGetPanel(room_obj.name, panel_it.first.as()); + Panel &panel_obj = panels_[panel_id]; + + if (panel_it.second["colors"]) { + if (panel_it.second["colors"].IsScalar()) { + panel_obj.colors.push_back( + GetColorForString(panel_it.second["colors"].as())); + } else { + for (const auto &color_node : panel_it.second["colors"]) { + panel_obj.colors.push_back( + GetColorForString(color_node.as())); + } + } + } + + if (panel_it.second["required_room"]) { + if (panel_it.second["required_room"].IsScalar()) { + panel_obj.required_rooms.push_back(AddOrGetRoom( + panel_it.second["required_room"].as())); + } else { + for (const auto &rr_node : panel_it.second["required_room"]) { + panel_obj.required_rooms.push_back( + AddOrGetRoom(rr_node.as())); + } + } + } + + if (panel_it.second["required_door"]) { + if (panel_it.second["required_door"].IsMap()) { + std::string rd_room = room_obj.name; + if (panel_it.second["required_door"]["room"]) { + rd_room = + panel_it.second["required_door"]["room"].as(); + } + + panel_obj.required_doors.push_back(AddOrGetDoor( + rd_room, + panel_it.second["required_door"]["door"].as())); + } else { + for (const auto &rr_node : panel_it.second["required_door"]) { + std::string rd_room = room_obj.name; + if (rr_node["room"]) { + rd_room = rr_node["room"].as(); + } + + panel_obj.required_doors.push_back( + AddOrGetDoor(rd_room, rr_node["door"].as())); + } + } + } + + if (panel_it.second["check"]) { + panel_obj.check = panel_it.second["check"].as(); + } + + if (panel_it.second["exclude_reduce"]) { + panel_obj.exclude_reduce = + panel_it.second["exclude_reduce"].as(); + } + } + } + + if (room_it.second["doors"]) { + for (const auto &door_it : room_it.second["doors"]) { + int door_id = + AddOrGetDoor(room_obj.name, door_it.first.as()); + Door &door_obj = doors_[door_id]; + + bool has_external_panels = false; + std::vector panel_names; + + for (const auto &panel_node : door_it.second["panels"]) { + if (panel_node.IsScalar()) { + panel_names.push_back(panel_node.as()); + door_obj.panels.push_back( + AddOrGetPanel(room_obj.name, panel_node.as())); + } else { + has_external_panels = true; + panel_names.push_back(panel_node["panel"].as()); + door_obj.panels.push_back( + AddOrGetPanel(panel_node["room"].as(), + panel_node["panel"].as())); + } + } + + if (door_it.second["skip_location"]) { + door_obj.skip_location = door_it.second["skip_location"].as(); + } + + if (door_it.second["item_name"]) { + door_obj.item_name = door_it.second["item_name"].as(); + } else if (!door_it.second["skip_item"] && !door_it.second["event"]) { + door_obj.item_name = room_obj.name + " - " + door_obj.name; + } + + if (door_it.second["group"]) { + door_obj.group_name = door_it.second["group"].as(); + } + + if (door_it.second["location_name"]) { + door_obj.location_name = + door_it.second["location_name"].as(); + } else if (!door_it.second["skip_location"] && + !door_it.second["event"]) { + if (has_external_panels) { + std::cout + << room_obj.name << " - " << door_obj.name + << " has panels from other rooms but does not have an explicit " + "location name and is not marked skip_location or event" + << std::endl; + } + + door_obj.location_name = + room_obj.name + " - " + hatkirby::implode(panel_names, ", "); + } + + if (door_it.second["include_reduce"]) { + door_obj.exclude_reduce = + !door_it.second["include_reduce"].as(); + } + } + } + } +} + +int GameData::AddOrGetRoom(std::string room) { + if (!room_by_id_.count(room)) { + room_by_id_[room] = rooms_.size(); + rooms_.push_back({.name = room}); + } + + return room_by_id_[room]; +} + +int GameData::AddOrGetDoor(std::string room, std::string door) { + std::string full_name = room + " - " + door; + + if (!door_by_id_.count(full_name)) { + door_by_id_[full_name] = doors_.size(); + doors_.push_back({.name = door, .room = AddOrGetRoom(room)}); + } + + return door_by_id_[full_name]; +} + +int GameData::AddOrGetPanel(std::string room, std::string panel) { + std::string full_name = room + " - " + panel; + + if (!panel_by_id_.count(full_name)) { + panel_by_id_[full_name] = panels_.size(); + panels_.push_back({.name = panel, .room = AddOrGetRoom(room)}); + } + + return panel_by_id_[full_name]; +} + +const GameData &GetGameData() { + static GameData *instance = new GameData(); + return *instance; +} diff --git a/game_data.h b/game_data.h new file mode 100644 index 0000000..f74f033 --- /dev/null +++ b/game_data.h @@ -0,0 +1,86 @@ +#ifndef GAME_DATA_H_9C42AC51 +#define GAME_DATA_H_9C42AC51 + +#include +#include +#include + +enum class LingoColor { + kNone, + kBlack, + kRed, + kBlue, + kYellow, + kGreen, + kOrange, + kPurple, + kBrown, + kGray +}; + +struct Panel { + int room; + std::string name; + std::vector colors; + std::vector required_rooms; + std::vector required_doors; + bool check = false; + bool exclude_reduce = false; +}; + +struct Door { + int room; + std::string name; + std::string location_name; + std::string item_name; + std::string group_name; + bool skip_location = false; + std::vector panels; + bool exclude_reduce = true; +}; + +struct Exit { + int destination_room; + std::optional door; +}; + +struct Room { + std::string name; + std::vector exits; +}; + +struct Location { + std::string name; + int location_id; + int room; + std::vector panels; +}; + +struct MapArea { + std::string name; + std::vector locations; + int map_x; + int map_y; +}; + +class GameData { +public: + GameData(); + +private: + int AddOrGetRoom(std::string room); + int AddOrGetDoor(std::string room, std::string door); + int AddOrGetPanel(std::string room, std::string panel); + + std::vector rooms_; + std::vector doors_; + std::vector panels_; + + std::map room_by_id_; + std::map door_by_id_; + std::map panel_by_id_; +}; + +const GameData &GetGameData(); + +#endif /* end of include guard: GAME_DATA_H_9C42AC51 */ diff --git a/vendor/hkutil b/vendor/hkutil new file mode 160000 index 0000000..bfe86f5 --- /dev/null +++ b/vendor/hkutil @@ -0,0 +1 @@ +Subproject commit bfe86f537030739f2f82c3e2ddcbe97eff7ef0ed -- cgit 1.4.1