#include "identifiers.h"
#include <string>
#include "proto/human.pb.h"
namespace com::fourisland::lingo2_archipelago {
std::optional<RoomIdentifier> GetCompleteRoomIdentifier(
RoomIdentifier identifier, std::optional<std::string> map_name) {
if (!identifier.has_map()) {
if (!map_name) {
return std::nullopt;
}
identifierpre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */#include <google/protobuf/message.h>
#include <google/protobuf/text_format.h>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include "proto/human.pb.h"
#include "util/ids_yaml_format.h"
#include "util/naming.h"
namespace com::fourisland::lingo2_archipelago {
namespace {
template <typename T>
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 AssignIds {
public:
AssignIds(const std::string& mapdir) : mapdir_(mapdir) {}
void Run() {
std::filesystem::path datadir_path = mapdir_;
std::filesystem::path ids_path = datadir_path / "ids.yaml";
ReadIds(ids_path);
ProcessMaps(datadir_path);
ProcessSpecialIds();
ProcessProgressivesFile(datadir_path / "progressives.txtpb");
ProcessDoorGroupsFile(datadir_path / "door_groups.txtpb");
WriteIds(ids_path);
std::cout << "Next ID: " << next_id_ << std::endl;
}
void ReadIds(std::filesystem::path path) {
if (!std::filesystem::exists(path)) {
return;
}
id_mappings_ = ReadIdsFromYaml(path.string());
for (const auto& [_, map] : id_mappings_.maps()) {
UpdateNextId(map.doors());
for (const auto& [_, room] : map.rooms()) {
UpdateNextId(room.panels());
UpdateNextId(room.masteries());
UpdateNextId(room.keyholders());
}
}
UpdateNextId(id_mappings_.special());
UpdateNextId(id_mappings_.letters());
UpdateNextId(id_mappings_.endings());
UpdateNextId(id_mappings_.progressives());
UpdateNextId(id_mappings_.door_groups());
next_id_++;
}
void WriteIds(std::filesystem::path path) {
WriteIdsAsYaml(output_, path.string());
}
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();
ProcessDoorsFile(path / "doors.txtpb", map_name);
ProcessRooms(path / "rooms", map_name);
}
void ProcessDoorsFile(std::filesystem::path path,
const std::string& current_map_name) {
if (!std::filesystem::exists(path)) {
return;
}
auto doors = ReadMessageFromFile<HumanDoors>(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) {
if (h_door.type() == DoorType::EVENT) {
return;
}
auto& maps = *output_.mutable_maps();
auto& doors = *maps[current_map_name].mutable_doors();
if (!id_mappings_.maps().contains(current_map_name) ||
!id_mappings_.maps()
.at(current_map_name)
.doors()
.contains(h_door.name())) {
doors[h_door.name()] = next_id_++;
} else {
doors[h_door.name()] =
id_mappings_.maps().at(current_map_name).doors().at(h_door.name());
}
}
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<HumanRoom>(dir_entry.path().string());
ProcessRoom(room, current_map_name);
}
}
void ProcessRoom(const HumanRoom& h_room,
const std::string& current_map_name) {
for (const HumanPanel& h_panel : h_room.panels()) {
auto& maps = *output_.mutable_maps();
auto& rooms = *maps[current_map_name].mutable_rooms();
auto& panels = *rooms[h_room.name()].mutable_panels();
if (!id_mappings_.maps().contains(current_map_name) ||
!id_mappings_.maps()
.at(current_map_name)
.rooms()
.contains(h_room.name()) ||
!id_mappings_.maps()
.at(current_map_name)
.rooms()
.at(h_room.name())
.panels()
.contains(h_panel.name())) {
panels[h_panel.name()] = next_id_++;
} else {
panels[h_panel.name()] = id_mappings_.maps()
.at(current_map_name)
.rooms()
.at(h_room.name())
.panels()
.at(h_panel.name());
}
}
for (const HumanLetter& h_letter : h_room.letters()) {
std::string lettername = GetLetterName(h_letter.key(), h_letter.level2());
auto& letters = *output_.mutable_letters();
if (!id_mappings_.letters().contains(lettername)) {
letters[lettername] = next_id_++;
} else {
letters[lettername] = id_mappings_.letters().at(lettername);
}
}
for (const HumanMastery& h_mastery : h_room.masteries()) {
auto& maps = *output_.mutable_maps();
auto& rooms = *maps[current_map_name].mutable_rooms();
auto& masteries = *rooms[h_room.name()].mutable_masteries();
if (!id_mappings_.maps().contains(current_map_name) ||
!id_mappings_.maps()
.at(current_map_name)
.rooms()
.contains(h_room.name()) ||
!id_mappings_.maps()
.at(current_map_name)
.rooms()
.at(h_room.name())
.masteries()
.contains(h_mastery.name())) {
masteries[h_mastery.name()] = next_id_++;
} else {
masteries[h_mastery.name()] = id_mappings_.maps()
.at(current_map_name)
.rooms()
.at(h_room.name())
.masteries()
.at(h_mastery.name());
}
}
for (const HumanEnding& h_ending : h_room.endings()) {
auto& endings = *output_.mutable_endings();
if (!id_mappings_.endings().contains(h_ending.name())) {
endings[h_ending.name()] = next_id_++;
} else {
endings[h_ending.name()] = id_mappings_.endings().at(h_ending.name());
}
}
for (const HumanKeyholder& h_keyholder : h_room.keyholders()) {
if (!h_keyholder.has_key()) {
continue;
}
auto& maps = *output_.mutable_maps();
auto& rooms = *maps[current_map_name].mutable_rooms();
auto& keyholders = *rooms[h_room.name()].mutable_keyholders();
if (!id_mappings_.maps().contains(current_map_name) ||
!id_mappings_.maps()
.at(current_map_name)
.rooms()
.contains(h_room.name()) ||
!id_mappings_.maps()
.at(current_map_name)
.rooms()
.at(h_room.name())
.keyholders()
.contains(h_keyholder.name())) {
keyholders[h_keyholder.name()] = next_id_++;
} else {
keyholders[h_keyholder.name()] = id_mappings_.maps()
.at(current_map_name)
.rooms()
.at(h_room.name())
.keyholders()
.at(h_keyholder.name());
}
}
}
void ProcessSpecialIds() {
auto& specials = *output_.mutable_special();
for (const auto& [special_name, ap_id] : id_mappings_.special()) {
specials[special_name] = ap_id;
}
}
void ProcessProgressivesFile(std::filesystem::path path) {
if (!std::filesystem::exists(path)) {
return;
}
auto h_progs = ReadMessageFromFile<HumanProgressives>(path.string());
auto& progs = *output_.mutable_progressives();
for (const HumanProgressive& h_prog : h_progs.progressives()) {
if (!id_mappings_.progressives().contains(h_prog.name())) {
progs[h_prog.name()] = next_id_++;
} else {
progs[h_prog.name()] = id_mappings_.progressives().at(h_prog.name());
}
}
}
void ProcessDoorGroupsFile(std::filesystem::path path) {
if (!std::filesystem::exists(path)) {
return;
}
auto h_groups = ReadMessageFromFile<HumanDoorGroups>(path.string());
auto& groups = *output_.mutable_door_groups();
for (const HumanDoorGroup& h_group : h_groups.door_groups()) {
if (!id_mappings_.door_groups().contains(h_group.name())) {
groups[h_group.name()] = next_id_++;
} else {
groups[h_group.name()] = id_mappings_.door_groups().at(h_group.name());
}
}
}
private:
void UpdateNextId(const google::protobuf::Map<std::string, uint64_t>& ids) {
for (const auto& [_, id] : ids) {
if (id > next_id_) {
next_id_ = id;
}
}
}
std::string mapdir_;
uint64_t next_id_ = 1;
IdMappings id_mappings_;
IdMappings output_;
};
} // namespace
} // namespace com::fourisland::lingo2_archipelago
int main(int argc, char** argv) {
if (argc != 2) {
std::cout << "Incorrect argument count." << std::endl;
std::cout << "Usage: assign_ids [path to map directory]" << std::endl;
return 1;
}
std::string mapdir = argv[1];
com::fourisland::lingo2_archipelago::AssignIds assign_ids(mapdir);
assign_ids.Run();
return 0;
}