From e9d9da34e86a1e5f0de155bf9086d3e5ff6b2da0 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Thu, 7 Aug 2025 13:34:42 -0400 Subject: Protobuf works! Parsing connections --- tools/datapacker/CMakeLists.txt | 10 ++ tools/datapacker/container.cpp | 205 ++++++++++++++++++++++++++++++++++++++++ tools/datapacker/container.h | 65 +++++++++++++ tools/datapacker/main.cpp | 196 +++++++++++++++++++++++++++++++++++++- 4 files changed, 473 insertions(+), 3 deletions(-) create mode 100644 tools/datapacker/CMakeLists.txt create mode 100644 tools/datapacker/container.cpp create mode 100644 tools/datapacker/container.h (limited to 'tools/datapacker') diff --git a/tools/datapacker/CMakeLists.txt b/tools/datapacker/CMakeLists.txt new file mode 100644 index 0000000..0274043 --- /dev/null +++ b/tools/datapacker/CMakeLists.txt @@ -0,0 +1,10 @@ +find_package(Protobuf REQUIRED) + +add_executable(datapacker + main.cpp + container.cpp +) +set_property(TARGET datapacker PROPERTY CXX_STANDARD 20) +set_property(TARGET datapacker PROPERTY CXX_STANDARD_REQUIRED ON) +target_include_directories(datapacker PUBLIC ${CMAKE_BINARY_DIR}) +target_link_libraries(datapacker PUBLIC protos protobuf::libprotobuf) diff --git a/tools/datapacker/container.cpp b/tools/datapacker/container.cpp new file mode 100644 index 0000000..ead3818 --- /dev/null +++ b/tools/datapacker/container.cpp @@ -0,0 +1,205 @@ +#include "container.h" + +namespace com::fourisland::lingo2_archipelago { + +uint64_t Container::FindOrAddMap(std::string map_name) { + auto it = map_id_by_name_.find(map_name); + + if (it == map_id_by_name_.end()) { + uint64_t new_id = all_objects_.maps_size(); + Map* map = all_objects_.add_maps(); + map->set_id(new_id); + map->set_name(map_name); + + map_id_by_name_[map_name] = new_id; + + return new_id; + } else { + return it->second; + } +} + +uint64_t Container::FindOrAddRoom(std::optional map_name, + std::string room_name, + std::optional map_fallback) { + if (!map_name) { + if (!map_fallback) { + std::cout << "No map name provided for " << room_name << std::endl; + map_name = "global"; + } else { + map_name = map_fallback; + } + } + + auto& map_container = room_id_by_map_room_names_[*map_name]; + auto it = map_container.find(room_name); + if (it == map_container.end()) { + uint64_t new_id = all_objects_.rooms_size(); + Room* room = all_objects_.add_rooms(); + room->set_id(new_id); + room->set_map_id(FindOrAddMap(*map_name)); + room->set_name(room_name); + + map_container[room_name] = new_id; + + return new_id; + } else { + return it->second; + } +} + +uint64_t Container::FindOrAddPainting( + std::optional map_name, std::optional room_name, + std::string painting_name, std::optional map_fallback, + std::optional room_fallback) { + if (!map_name) { + if (!map_fallback) { + std::cout << "No map name provided for " << painting_name << std::endl; + map_name = "global"; + } else { + map_name = map_fallback; + } + } + + if (!room_name) { + if (!room_fallback) { + std::cout << "No room name provided for " << painting_name << std::endl; + room_name = "global"; + } else { + room_name = room_fallback; + } + } + + auto& room_container = + painting_id_by_map_room_painting_names_[*map_name][*room_name]; + auto it = room_container.find(painting_name); + if (it == room_container.end()) { + uint64_t new_id = all_objects_.paintings_size(); + Painting* painting = all_objects_.add_paintings(); + painting->set_id(new_id); + painting->set_room_id(FindOrAddRoom(map_name, *room_name, std::nullopt)); + painting->set_name(painting_name); + + room_container[painting_name] = new_id; + + return new_id; + } else { + return it->second; + } +} + +uint64_t Container::FindOrAddPort(std::optional map_name, + std::optional room_name, + std::string port_name, + std::optional map_fallback, + std::optional room_fallback) { + if (!map_name) { + if (!map_fallback) { + std::cout << "No map name provided for " << port_name << std::endl; + map_name = "global"; + } else { + map_name = map_fallback; + } + } + + if (!room_name) { + if (!room_fallback) { + std::cout << "No room name provided for " << port_name << std::endl; + room_name = "global"; + } else { + room_name = room_fallback; + } + } + + auto& room_container = port_id_by_map_room_port_names_[*map_name][*room_name]; + auto it = room_container.find(port_name); + if (it == room_container.end()) { + uint64_t new_id = all_objects_.ports_size(); + Port* port = all_objects_.add_ports(); + port->set_id(new_id); + port->set_room_id(FindOrAddRoom(map_name, *room_name, std::nullopt)); + port->set_name(port_name); + + room_container[port_name] = new_id; + + return new_id; + } else { + return it->second; + } +} + +uint64_t Container::FindOrAddPanel(std::optional map_name, + std::optional room_name, + std::string panel_name, + std::optional map_fallback, + std::optional room_fallback) { + if (!map_name) { + if (!map_fallback) { + std::cout << "No map name provided for " << panel_name << std::endl; + map_name = "global"; + } else { + map_name = map_fallback; + } + } + + if (!room_name) { + if (!room_fallback) { + std::cout << "No room name provided for " << panel_name << std::endl; + room_name = "global"; + } else { + room_name = room_fallback; + } + } + + auto& room_container = + panel_id_by_map_room_panel_names_[*map_name][*room_name]; + auto it = room_container.find(panel_name); + if (it == room_container.end()) { + uint64_t new_id = all_objects_.panels_size(); + Panel* panel = all_objects_.add_panels(); + panel->set_id(new_id); + panel->set_room_id(FindOrAddRoom(map_name, *room_name, std::nullopt)); + panel->set_name(panel_name); + + room_container[panel_name] = new_id; + + return new_id; + } else { + return it->second; + } +} + +uint64_t Container::FindOrAddDoor(std::optional map_name, + std::string door_name, + std::optional map_fallback) { + if (!map_name) { + if (!map_fallback) { + std::cout << "No map name provided for " << door_name << std::endl; + map_name = "global"; + } else { + map_name = map_fallback; + } + } + + auto& map_container = door_id_by_map_door_names_[*map_name]; + auto it = map_container.find(door_name); + if (it == map_container.end()) { + uint64_t new_id = all_objects_.doors_size(); + Door* door = all_objects_.add_doors(); + door->set_id(new_id); + door->set_map_id(FindOrAddMap(*map_name)); + door->set_name(door_name); + + map_container[door_name] = new_id; + + return new_id; + } else { + return it->second; + } +} + +void Container::AddConnection(const Connection& connection) { + *all_objects_.add_connections() = connection; +} + +} // namespace com::fourisland::lingo2_archipelago diff --git a/tools/datapacker/container.h b/tools/datapacker/container.h new file mode 100644 index 0000000..96e5a50 --- /dev/null +++ b/tools/datapacker/container.h @@ -0,0 +1,65 @@ +#ifndef TOOLS_DATAPACKER_CONTAINER_H_ +#define TOOLS_DATAPACKER_CONTAINER_H_ + +#include +#include +#include +#include + +#include "proto/data.pb.h" + +namespace com::fourisland::lingo2_archipelago { + +class Container { + public: + uint64_t FindOrAddMap(std::string map_name); + + uint64_t FindOrAddRoom(std::optional map_name, + std::string room_name, + std::optional map_fallback); + + uint64_t FindOrAddPainting(std::optional map_name, + std::optional room_name, + std::string painting_name, + std::optional map_fallback, + std::optional room_fallback); + + uint64_t FindOrAddPort(std::optional map_name, + std::optional room_name, + std::string port_name, + std::optional map_fallback, + std::optional room_fallback); + + uint64_t FindOrAddPanel(std::optional map_name, + std::optional room_name, + std::string panel_name, + std::optional map_fallback, + std::optional room_fallback); + + uint64_t FindOrAddDoor(std::optional map_name, + std::string door_name, + std::optional map_fallback); + + void AddConnection(const Connection& connection); + + const AllObjects& all_objects() const { return all_objects_; } + + private: + AllObjects all_objects_; + + std::map map_id_by_name_; + std::map> + room_id_by_map_room_names_; + std::map>> + painting_id_by_map_room_painting_names_; + std::map>> + port_id_by_map_room_port_names_; + std::map>> + panel_id_by_map_room_panel_names_; + std::map> + door_id_by_map_door_names_; +}; + +} // namespace com::fourisland::lingo2_archipelago + +#endif /* TOOLS_DATAPACKER_CONTAINER_H_ */ diff --git a/tools/datapacker/main.cpp b/tools/datapacker/main.cpp index fd0ace6..b2ec068 100644 --- a/tools/datapacker/main.cpp +++ b/tools/datapacker/main.cpp @@ -1,21 +1,211 @@ +#include +#include + +#include +#include +#include #include +#include +#include +#include #include -void Run(const std::string& mapdir, const std::string& outputpath) { +#include "container.h" +#include "proto/data.pb.h" +#include "proto/human.pb.h" + +namespace com::fourisland::lingo2_archipelago { +namespace { + +template +T ReadMessageFromFile(const std::string& path) { + std::ifstream file(path); + std::stringstream buffer; + buffer << file.rdbuf(); + T message; + google::protobuf::TextFormat::ParseFromString(buffer.str(), &message); + + return message; } +class DataPacker { + public: + DataPacker(const std::string& mapdir, const std::string& outputpath) + : mapdir_(mapdir), outputpath_(outputpath) {} + + void Run() { + std::filesystem::path datadir_path = mapdir_; + + ProcessConnectionsFile(datadir_path / "connections.txtpb", std::nullopt); + + { + std::ofstream outputfile(outputpath_); + container_.all_objects().SerializeToOstream(&outputfile); + } + + std::string output; + google::protobuf::TextFormat::PrintToString(container_.all_objects(), + &output); + std::cout << output << std::endl; + } + + private: + void ProcessConnectionsFile(std::filesystem::path path, + std::optional current_map_name) { + if (!std::filesystem::exists(path)) { + return; + } + + auto connections = ReadMessageFromFile(path.string()); + + for (const HumanConnection& connection : connections.connections()) { + ProcessConnection(connection, current_map_name); + } + } + + void ProcessConnection(const HumanConnection& human_connection, + const std::optional& current_map_name) { + Connection f_connection; + + if (human_connection.has_from_room()) { + f_connection.set_from_room(container_.FindOrAddRoom( + std::nullopt, human_connection.from_room(), current_map_name)); + } else if (human_connection.has_from()) { + ProcessSingleConnection(human_connection.from(), current_map_name, + f_connection); + } + + Connection r_connection; + r_connection.set_to_room(f_connection.from_room()); + + if (human_connection.has_to_room()) { + r_connection.set_to_room(container_.FindOrAddRoom( + std::nullopt, human_connection.to_room(), current_map_name)); + } else if (human_connection.has_to()) { + ProcessSingleConnection(human_connection.to(), current_map_name, + r_connection); + } + + f_connection.set_to_room(r_connection.from_room()); + + if (human_connection.has_door()) { + std::optional map_name = + human_connection.door().has_map() + ? std::optional(human_connection.door().map()) + : std::nullopt; + uint64_t door_id = container_.FindOrAddDoor( + map_name, human_connection.door().name(), current_map_name); + f_connection.set_required_door(door_id); + r_connection.set_required_door(door_id); + } + + container_.AddConnection(f_connection); + if (!human_connection.oneway()) { + container_.AddConnection(r_connection); + } + } + + void ProcessSingleConnection( + const HumanConnection::Endpoint& endpoint, + const std::optional& current_map_name, + Connection& connection) { + if (endpoint.has_room()) { + std::optional map_name = + endpoint.room().has_map() + ? std::optional(endpoint.room().map()) + : std::nullopt; + connection.set_from_room(container_.FindOrAddRoom( + map_name, endpoint.room().name(), current_map_name)); + } else if (endpoint.has_painting()) { + std::optional map_name = + endpoint.painting().has_map() + ? std::optional(endpoint.painting().map()) + : std::nullopt; + + std::string room_name; + if (!endpoint.painting().has_room()) { + std::cout << "Missing room name for painting " + << endpoint.painting().name() << std::endl; + room_name = "default"; + } else { + room_name = endpoint.painting().room(); + } + + connection.set_from_room( + container_.FindOrAddRoom(map_name, room_name, current_map_name)); + connection.set_painting(container_.FindOrAddPainting( + map_name, room_name, endpoint.painting().name(), current_map_name, + std::nullopt)); + } else if (endpoint.has_port()) { + std::optional map_name = + endpoint.port().has_map() + ? std::optional(endpoint.port().map()) + : std::nullopt; + + std::string room_name; + if (!endpoint.port().has_room()) { + std::cout << "Missing room name for port " << endpoint.port().name() + << std::endl; + room_name = "default"; + } else { + room_name = endpoint.port().room(); + } + + connection.set_from_room( + container_.FindOrAddRoom(map_name, room_name, current_map_name)); + connection.set_port( + container_.FindOrAddPort(map_name, room_name, endpoint.port().name(), + current_map_name, std::nullopt)); + } else if (endpoint.has_panel()) { + std::optional map_name = + endpoint.panel().has_map() + ? std::optional(endpoint.panel().map()) + : std::nullopt; + + std::string room_name; + if (!endpoint.panel().has_room()) { + std::cout << "Missing room name for panel " << endpoint.panel().name() + << std::endl; + room_name = "default"; + } else { + room_name = endpoint.panel().room(); + } + + connection.set_from_room( + container_.FindOrAddRoom(map_name, room_name, current_map_name)); + connection.mutable_panel()->set_panel(container_.FindOrAddPanel( + map_name, room_name, endpoint.panel().name(), current_map_name, + std::nullopt)); + if (endpoint.panel().has_answer()) { + connection.mutable_panel()->set_answer(endpoint.panel().answer()); + } + } + } + + std::string mapdir_; + std::string outputpath_; + + Container container_; +}; + +} // namespace +} // namespace com::fourisland::lingo2_archipelago + int main(int argc, char** argv) { if (argc != 3) { std::cout << "Incorrect argument count." << std::endl; - std::cout << "Usage: datapacker [path to map directory] [output file]" << std::endl; + std::cout << "Usage: datapacker [path to map directory] [output file]" + << std::endl; return 1; } std::string mapdir = argv[1]; std::string outputpath = argv[2]; - Run(mapdir, outputpath); + com::fourisland::lingo2_archipelago::DataPacker data_packer(mapdir, + outputpath); + data_packer.Run(); return 0; } -- cgit 1.4.1