#include #include #include #include #include #include #include #include #include #include #include #include "container.h" #include "proto/data.pb.h" #include "proto/human.pb.h" #include "util/ids_yaml_format.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 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); ProcessMaps(datadir_path); ProcessProgressivesFile(datadir_path / "progressives.txtpb"); ProcessDoorGroupsFile(datadir_path / "door_groups.txtpb"); ProcessIdsFile(datadir_path / "ids.yaml"); { 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 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(); ProcessMapMetadataFile(path / "metadata.txtpb", map_name); ProcessConnectionsFile(path / "connections.txtpb", map_name); ProcessDoorsFile(path / "doors.txtpb", map_name); ProcessRooms(path / "rooms", map_name); } void ProcessMapMetadataFile(std::filesystem::path path, const std::string& map_name) { if (!std::filesystem::exists(path)) { return; } auto metadata = ReadMessageFromFile(path.string()); uint64_t map_id = container_.FindOrAddMap(map_name); Map& map = *container_.all_objects().mutable_maps(map_id); if (metadata.has_display_name()) { map.set_display_name(metadata.display_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(dir_entry.path().string()); ProcessRoom(room, current_map_name); } } void ProcessRoom(const HumanRoom& h_room, const std::string& current_map_name) { uint64_t room_id = container_.FindOrAddRoom(current_map_name, h_room.name(), std::nullopt); Room& room = *container_.all_objects().mutable_rooms(room_id); // room.set_display_name(h_room.display_name()); if (h_room.has_panel_display_name()) { room.set_panel_display_name(h_room.panel_display_name()); } for (const HumanPanel& h_panel : h_room.panels()) { room.add_panels(ProcessPanel(h_panel, current_map_name, room.name())); } for (const HumanPainting& h_painting : h_room.paintings()) { room.add_paintings( ProcessPainting(h_painting, current_map_name, room.name())); } for (const HumanPort& h_port : h_room.ports()) { room.add_ports(ProcessPort(h_port, current_map_name, room.name())); } for (const HumanLetter& h_letter : h_room.letters()) { room.add_letters(ProcessLetter(h_letter, current_map_name, room.name())); } for (const HumanMastery& h_mastery : h_room.masteries()) { room.add_masteries( ProcessMastery(h_mastery, current_map_name, room.name())); } for (const HumanKeyholder& h_keyholder : h_room.keyholders()) { room.add_keyholders( ProcessKeyholder(h_keyholder, current_map_name, room.name())); } for (const HumanEnding& h_ending : h_room.endings()) { room.add_endings(ProcessEnding(h_ending, current_map_name, room.name())); } } uint64_t ProcessPanel(const HumanPanel& h_panel, const std::string& current_map_name, const std::string& current_room_name) { uint64_t panel_id = container_.FindOrAddPanel(current_map_name, current_room_name, h_panel.name(), std::nullopt, std::nullopt); PanelData& panel = *container_.all_objects().mutable_panels(panel_id); panel.set_path(h_panel.path()); panel.set_clue(h_panel.clue()); panel.set_answer(h_panel.answer()); std::copy( h_panel.symbols().begin(), h_panel.symbols().end(), google::protobuf::RepeatedFieldBackInserter(panel.mutable_symbols())); std::copy( h_panel.proxies().begin(), h_panel.proxies().end(), google::protobuf::RepeatedFieldBackInserter(panel.mutable_proxies())); if (h_panel.has_required_door()) { std::optional map_name = h_panel.required_door().has_map() ? std::optional(h_panel.required_door().map()) : std::nullopt; panel.set_required_door(container_.FindOrAddDoor( map_name, h_panel.required_door().name(), current_map_name)); } if (h_panel.has_required_room()) { std::optional map_name = h_panel.required_room().has_map() ? std::optional(h_panel.required_room().map()) : std::nullopt; panel.set_required_room(container_.FindOrAddRoom( map_name, h_panel.required_room().name(), current_map_name)); } if (h_panel.has_display_name()) { panel.set_display_name(h_panel.display_name()); } return panel_id; } uint64_t ProcessPainting(const HumanPainting& h_painting, const std::string& current_map_name, const std::string& current_room_name) { uint64_t painting_id = container_.FindOrAddPainting( current_map_name, current_room_name, h_painting.name(), std::nullopt, std::nullopt); PaintingData& painting = *container_.all_objects().mutable_paintings(painting_id); painting.set_path(h_painting.path()); painting.set_display_name(h_painting.display_name()); painting.set_orientation(h_painting.orientation()); // Setting this explicitly because the Godot protobuf doesn't support // custom defaults. painting.set_gravity(h_painting.gravity()); if (h_painting.has_move()) { painting.set_move(h_painting.move()); } if (h_painting.has_enter_only()) { painting.set_enter_only(h_painting.enter_only()); }
#ifndef TOOLS_VALIDATOR_STRUCTS_H_
#define TOOLS_VALIDATOR_STRUCTS_H_

#include <map>
#include <string>
#include <vector>

#include "proto/human.pb.h"
#include "util/identifiers.h"

namespace com::fourisland::lingo2_archipelago {

struct MalformedIdentifiers {
  std::vector<PaintingIdentifier> paintings;
  std::vector<PanelIdentifier> panels;
  std::vector<KeyholderIdentifier> keyholders;

  bool HasAny() const {
    return !paintings.empty() || !panels.empty() || !keyholders.empty();
  }
};

struct GameNodeInfo {
  bool defined = false;
  int uses = 0;
};

struct MapInfo {
  std::map<std::string, GameNodeInfo> game_nodes;
};

struct RoomInfo {
  std::vector<HumanRoom> definitions;

  std::vector<DoorIdentifier> doors_referenced_by;
  std::vector<PanelIdentifier> panels_referenced_by;
  std::vector<HumanConnection> connections_referenced_by;
};

struct DoorInfo {
  std::vector<HumanDoor> definitions;

  std::vector<HumanConnection> connections_referenced_by;
  std::vector<DoorIdentifier> doors_referenced_by;
  std::vector<PanelIdentifier> panels_referenced_by;
  std::vector<PaintingIdentifier> paintings_referenced_by;
  std::vector<PortIdentifier> ports_referenced_by;

  MalformedIdentifiers malformed_identifiers;
};

struct PortInfo {
  std::vector<HumanPort> definitions;

  std::vector<HumanConnection> connections_referenced_by;
};

struct PaintingInfo {
  std::vector<HumanPainting> definitions;

  std::vector<HumanConnection> connections_referenced_by;
  std::vector<DoorIdentifier> doors_referenced_by;
};

struct ProxyInfo {
  std::vector<Proxy> definitions;

  std::vector<HumanConnection> connections_referenced_by;
  std::vector<DoorIdentifier> doors_referenced_by;
};

struct PanelInfo {
  std::vector<HumanPanel> definitions;

  std::vector<HumanConnection> connections_referenced_by;
  std::vector<DoorIdentifier> doors_referenced_by;

  std::map<std::string, ProxyInfo> proxies;
};

struct KeyholderInfo {
  std::vector<HumanKeyholder> definitions;

  std::vector<DoorIdentifier> doors_referenced_by;
};

using LetterIdentifier = std::tuple<char, bool>;

struct LetterInfo {
  std::vector<RoomIdentifier> defined_in;
};

struct EndingInfo {
  std::vector<RoomIdentifier> defined_in;
};

struct CollectedInfo {
  std::map<std::string, MapInfo> maps;
  std::map<RoomIdentifier, RoomInfo, RoomIdentifierLess> rooms;
  std::map<DoorIdentifier, DoorInfo, DoorIdentifierLess> doors;
  std::map<PortIdentifier, PortInfo, PortIdentifierLess> ports;
  std::map<PaintingIdentifier, PaintingInfo, PaintingIdentifierLess> paintings;
  std::map<PanelIdentifier, PanelInfo, PanelIdentifierLess> panels;
  std::map<KeyholderIdentifier, KeyholderInfo, KeyholderIdentifierLess>
      keyholders;
  std::map<LetterIdentifier, LetterInfo> letters;
  std::map<std::string, EndingInfo> endings;
};

}  // namespace com::fourisland::lingo2_archipelago

#endif /* TOOLS_VALIDATOR_STRUCTS_H_ */