#include "human_processor.h" #include #include #include #include #include #include #include #include #include #include "structs.h" namespace com::fourisland::lingo2_archipelago { namespace { template T ReadMessageFromFile(const std::string& path) { std::cout << "Processing " << path << std::endl; std::ifstream file(path); std::stringstream buffer; buffer << file.rdbuf(); T message; google::protobuf::TextFormat::ParseFromString(buffer.str(), &message); return message; } class HumanProcessor { public: HumanProcessor(const std::string& mapdir, CollectedInfo& info) : mapdir_(mapdir), info_(info) {} void Run() { std::filesystem::path datadir_path = mapdir_; ProcessConnectionsFile(datadir_path / "connections.txtpb", std::nullopt); ProcessMaps(datadir_path); ProcessIdsFile(datadir_path / "ids.txtpb"); } private: void ProcessMaps(std::filesystem::path path) { std::filesystem::path maps_dir = path / "maps"; for (auto const& dir_entry : std::filesystem::directory_iterator(maps_dir)) { ProcessMap(dir_entry.path()); } } void ProcessMap(std::filesystem::path path) { std::string map_name = path.filename().string(); ProcessMetadataFile(path / "metadata.txtpb", map_name); ProcessConnectionsFile(path / "connections.txtpb", map_name); ProcessDoorsFile(path / "doors.txtpb", map_name); ProcessRooms(path / "rooms", map_name); } void ProcessMetadataFile(std::filesystem::path path, const std::string& current_map_name) { if (!std::filesystem::exists(path)) { return; } MapInfo& map_info = info_.maps[current_map_name]; auto metadata = ReadMessageFromFile(path.string()); for (const std::string& path : metadata.excluded_nodes()) { map_info.game_nodes[path].uses++; } } void ProcessRooms(std::filesystem::path path, const std::string& current_map_name) { for (auto const& dir_entry : std::filesystem::directory_iterator(path)) { auto room = ReadMessageFromFile(dir_entry.path().string()); ProcessRoom(room, current_map_name); } } void ProcessRoom(const HumanRoom& h_room, const std::string& current_map_name) { RoomIdentifier room_identifier; room_identifier.set_map(current_map_name); room_identifier.set_name(h_room.name()); RoomInfo& room_info = info_.rooms[room_identifier]; room_info.definitions.push_back(h_room); for (const HumanPanel& h_panel : h_room.panels()) { ProcessPanel(h_panel, current_map_name, h_room.name()); } for (const HumanPainting& h_painting : h_room.paintings()) { ProcessPainting(h_painting, current_map_name, h_room.name()); } for (const HumanPort& h_port : h_room.ports()) { ProcessPort(h_port, current_map_name, h_room.name()); } for (const HumanLetter& h_letter : h_room.letters()) { ProcessLetter(h_letter, current_map_name, h_room.name()); } for (const HumanMastery& h_mastery : h_room.masteries()) { ProcessMastery(h_mastery, current_map_name, h_room.name()); } for (const HumanKeyholder& h_keyholder : h_room.keyholders()) { ProcessKeyholder(h_keyholder, current_map_name, h_room.name()); } } void ProcessPanel(const HumanPanel& h_panel, const std::string& current_map_name, const std::string& current_room_name) { PanelIdentifier panel_identifier; panel_identifier.set_map(current_map_name); panel_identifier.set_room(current_room_name); panel_identifier.set_name(h_panel.name()); PanelInfo& panel_info = info_.panels[panel_identifier]; panel_info.definitions.push_back(h_panel); panel_info.proxies[h_panel.answer()].definitions.push_back(Proxy()); MapInfo& map_info = info_.maps[current_map_name]; map_info.game_nodes[h_panel.path()].uses++; for (const Proxy& h_proxy : h_panel.proxies()) { ProxyInfo& proxy_info = panel_info.proxies[h_proxy.answer()]; proxy_info.definitions.push_back(h_proxy); map_info.game_nodes[h_proxy.path()].uses++; } if (h_panel.has_required_door()) { DoorIdentifier required_door_identifier = *GetCompleteDoorIdentifier(h_panel.required_door(), current_map_name); DoorInfo& required_door_info = info_.doors[required_door_identifier]; required_door_info.panels_referenced_by.push_back(panel_identifier); } if (h_panel.has_required_room()) { RoomIdentifier required_room_identifier = *GetCompleteRoomIdentifier(h_panel.required_room(), current_map_name); RoomInfo& required_room_info = info_.rooms[required_room_identifier]; required_room_info.panels_referenced_by.push_back(panel_identifier); } } void ProcessPainting(const HumanPainting& h_painting, const std::string& current_map_name, const std::string& current_room_name) { PaintingIdentifier painting_identifier; painting_identifier.set_map(current_map_name); painting_identifier.set_room(current_room_name); painting_identifier.set_name(h_painting.name()); PaintingInfo& painting_info = info_.paintings[painting_identifier]; painting_info.definitions.push_back(h_painting); MapInfo& map_info = info_.maps[current_map_name]; map_info.game_nodes[h_painting.path()].uses++; if (h_painting.has_required_door()) { DoorIdentifier required_door_identifier = *GetCompleteDoorIdentifier( h_painting.required_door(), current_map_name); DoorInfo& required_door_info = info_.doors[required_door_identifier]; required_door_info.paintings_referenced_by.push_back(painting_identifier); } } void ProcessPort(const HumanPort& h_port, const std::string& current_map_name, const std::string& current_room_name) { PortIdentifier port_identifier; port_identifier.set_map(current_map_name); port_identifier.set_room(current_room_name); port_identifier.set_name(h_port.name()); PortInfo& port_info = info_.ports[port_identifier]; port_info.definitions.push_back(h_port); MapInfo& map_info = info_.maps[current_map_name]; map_info.game_nodes[h_port.path()].uses++; if (h_port.has_required_door()) { DoorIdentifier required_door_identifier = *GetCompleteDoorIdentifier(h_port.required_door(), current_map_name); DoorInfo& required_door_info = info_.doors[required_door_identifier]; required_door_info.ports_referenced_by.push_back(port_identifier); } } void ProcessLetter(const HumanLetter& h_letter, const std::string& current_map_name, const std::string& current_room_name) { LetterIdentifier letter_identifier = std::make_tuple(h_letter.key()[0], h_letter.level2()); LetterInfo& letter_info = info_.letters[letter_identifier]; RoomIdentifier room_identifier; room_identifier.set_map(current_map_name); room_identifier.set_name(current_room_name); letter_info.defined_in.push_back(room_identifier); MapInfo& map_info = info_.maps[current_map_name]; map_info.game_nodes[h_letter.path()].uses++; } void ProcessMastery(const HumanMastery& h_mastery, const std::string& current_map_name, const std::string& current_room_name) { MapInfo& map_info = info_.maps[current_map_name]; map_info.game_nodes[h_mastery.path()].uses++; } void ProcessKeyholder(const HumanKeyholder& h_keyholder, const std::string& current_map_name, const std::string& current_room_name) { KeyholderIdentifier keyholder_identifier; keyholder_identifier.set_map(current_map_name); keyholder_identifier.set_room(current_room_name); keyholder_identifier.set_name(h_keyholder.name()); KeyholderInfo& keyholder_info = info_.keyholders[keyholder_identifier]; keyholder_info.definitions.push_back(h_keyholder); MapInfo& map_info = info_.maps[current_map_name]; map_info.game_nodes[h_keyholder.path()].uses++; } void ProcessDoorsFile(std::filesystem::path path, const std::string& current_map_name) { if (!std::filesystem::exists(path)) { return; } auto doors = ReadMessageFromFile(path.string()); for (const HumanDoor& door : doors.doors()) { ProcessDoor(door, current_map_name); } } void ProcessDoor(const HumanDoor& h_door, const std::string& current_map_name) { DoorIdentifier door_identifier; door_identifier.set_map(current_map_name); door_identifier.set_name(h_door.name()); DoorInfo& door_info = info_.doors[door_identifier]; door_info.definitions.push_back(h_door); if (h_door.has_location_room()) { RoomIdentifier location_room_identifier; location_room_identifier.set_map(current_map_name); location_room_identifier.set_name(h_door.location_room()); info_.rooms[location_room_identifier].doors_referenced_by.push_back( door_identifier); } for (const PaintingIdentifier& pi : h_door.move_paintings()) { auto complete_painting_identifier = GetCompletePaintingIdentifier(pi, current_map_name, std::nullopt); if (complete_painting_identifier) { PaintingInfo& move_painting_info = info_.paintings[*complete_painting_identifier]; move_painting_info.doors_referenced_by.push_back(door_identifier); } else { door_info.malformed_identifiers.paintings.push_back(pi); } } for (const PanelIdentifier& pi : h_door.panels()) { auto complete_panel_identifier = GetCompletePanelIdentifierWithoutAnswer( pi, current_map_name, std::nullopt); if (complete_panel_identifier) { PanelInfo& panel_info = info_.panels[*complete_panel_identifier]; panel_info.doors_referenced_by.push_back(door_identifier); if (pi.has_answer()) { panel_info.proxies[pi.answer()].doors_referenced_by.push_back( door_identifier); } } else { door_info.malformed_identifiers.panels.push_back(pi); } } for (const KeyholderIdentifier& ki : h_door.keyholders()) { auto complete_keyholder_identifier = GetCompleteKeyholderIdentifierWithoutKey(ki, current_map_name, std::nullopt); if (complete_keyholder_identifier) { KeyholderInfo& keyholder_info = info_.keyholders[*complete_keyholder_identifier]; keyholder_info.doors_referenced_by.push_back(door_identifier); } else { door_info.malformed_identifiers.keyholders.push_back(ki); } } for (const RoomIdentifier& ri : h_door.rooms()) { RoomIdentifier complete_room_identifier = *GetCompleteRoomIdentifier(ri, current_map_name); RoomInfo& room_info = info_.rooms[complete_room_identifier]; room_info.doors_referenced_by.push_back(door_identifier); } for (const DoorIdentifier& di : h_door.doors()) { DoorIdentifier complete_door_identifier = *GetCompleteDoorIdentifier(di, current_map_name); DoorInfo& other_door_info = info_.doors[complete_door_identifier]; other_door_info.doors_referenced_by.push_back(door_identifier); } } 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) { if (human_connection.has_from_room()) { if (current_map_name) { RoomIdentifier room_identifier; room_identifier.set_map(*current_map_name); room_identifier.set_name(human_connection.from_room()); RoomInfo& room_info = info_.rooms[room_identifier]; room_info.connections_referenced_by.push_back(human_connection); } else { // Not sure where else to store this right now. std::cout << "A global connection used from_room." << std::endl; } } else if (human_connection.has_from()) { ProcessSingleConnection(human_connection, human_connection.from(), current_map_name); } if (human_connection.has_to_room()) { if (current_map_name) { RoomIdentifier room_identifier; room_identifier.set_map(*current_map_name); room_identifier.set_name(human_connection.to_room()); RoomInfo& room_info = info_.rooms[room_identifier]; room_info.connections_referenced_by.push_back(human_connection); } else { // Not sure where else to store this right now. std::cout << "A global connection used to_room." << std::endl; } } else if (human_connection.has_to()) { ProcessSingleConnection(human_connection, human_connection.to(), current_map_name); } if (human_connection.has_door()) { auto door_identifier = GetCompleteDoorIdentifier(human_connection.door(), current_map_name); if (door_identifier) { DoorInfo& door_info = info_.doors[*door_identifier]; door_info.connections_referenced_by.push_back(human_connection); } else { // Not sure where else to store this right now. std::cout << "A connection used the following malformed door identifier: " << human_connection.door().ShortDebugString() << std::endl; } } } void ProcessSingleConnection( const HumanConnection& human_connection, const HumanConnection::Endpoint& endpoint, const std::optional& current_map_name) { if (endpoint.has_room()) { auto room_identifier = GetCompleteRoomIdentifier(endpoint.room(), current_map_name); if (room_identifier) { RoomInfo& room_info = info_.rooms[*room_identifier]; room_info.connections_referenced_by.push_back(human_connection); } else { // Not sure where else to store this right now. std::cout << "A connection used the following malformed room identifier: " << endpoint.room().ShortDebugString() << std::endl; } } else if (endpoint.has_painting()) { auto painting_identifier = GetCompletePaintingIdentifier( endpoint.painting(), current_map_name, std::nullopt); if (painting_identifier) { PaintingInfo& painting_info = info_.paintings[*painting_identifier]; painting_info.connections_referenced_by.push_back(human_connection); } else { // Not sure where else to store this right now. std::cout << "A connection used the following malformed painting identifier: " << endpoint.painting().ShortDebugString() << std::endl; } } else if (endpoint.has_port()) { auto port_identifier = GetCompletePortIdentifier( endpoint.port(), current_map_name, std::nullopt); if (port_identifier) { PortInfo& port_info = info_.ports[*port_identifier]; port_info.connections_referenced_by.push_back(human_connection); } else { // Not sure where else to store this right now. std::cout << "A connection used the following malformed port identifier: " << endpoint.port().ShortDebugString() << std::endl; } } else if (endpoint.has_panel()) { auto panel_identifier = GetCompletePanelIdentifierWithoutAnswer( endpoint.panel(), current_map_name, std::nullopt); if (panel_identifier) { PanelInfo& panel_info = info_.panels[*panel_identifier]; panel_info.connections_referenced_by.push_back(human_connection); if (endpoint.panel().has_answer()) { panel_info.proxies[endpoint.panel().answer()] .connections_referenced_by.push_back(human_connection); } } } } void ProcessIdsFile(std::filesystem::path path) { // Ignore this for now. } std::string mapdir_; CollectedInfo& info_; }; } // namespace void ProcessHumanData(const std::string& mapdir, CollectedInfo& info) { HumanProcessor human_processor(mapdir, info); human_processor.Run(); } } // namespace com::fourisland::lingo2_archipelago