summary refs log tree commit diff stats
path: root/tools/datapacker
diff options
context:
space:
mode:
Diffstat (limited to 'tools/datapacker')
-rw-r--r--tools/datapacker/CMakeLists.txt10
-rw-r--r--tools/datapacker/container.cpp205
-rw-r--r--tools/datapacker/container.h65
-rw-r--r--tools/datapacker/main.cpp196
4 files changed, 473 insertions, 3 deletions
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 @@
1find_package(Protobuf REQUIRED)
2
3add_executable(datapacker
4 main.cpp
5 container.cpp
6)
7set_property(TARGET datapacker PROPERTY CXX_STANDARD 20)
8set_property(TARGET datapacker PROPERTY CXX_STANDARD_REQUIRED ON)
9target_include_directories(datapacker PUBLIC ${CMAKE_BINARY_DIR})
10target_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 @@
1#include "container.h"
2
3namespace com::fourisland::lingo2_archipelago {
4
5uint64_t Container::FindOrAddMap(std::string map_name) {
6 auto it = map_id_by_name_.find(map_name);
7
8 if (it == map_id_by_name_.end()) {
9 uint64_t new_id = all_objects_.maps_size();
10 Map* map = all_objects_.add_maps();
11 map->set_id(new_id);
12 map->set_name(map_name);
13
14 map_id_by_name_[map_name] = new_id;
15
16 return new_id;
17 } else {
18 return it->second;
19 }
20}
21
22uint64_t Container::FindOrAddRoom(std::optional<std::string> map_name,
23 std::string room_name,
24 std::optional<std::string> map_fallback) {
25 if (!map_name) {
26 if (!map_fallback) {
27 std::cout << "No map name provided for " << room_name << std::endl;
28 map_name = "global";
29 } else {
30 map_name = map_fallback;
31 }
32 }
33
34 auto& map_container = room_id_by_map_room_names_[*map_name];
35 auto it = map_container.find(room_name);
36 if (it == map_container.end()) {
37 uint64_t new_id = all_objects_.rooms_size();
38 Room* room = all_objects_.add_rooms();
39 room->set_id(new_id);
40 room->set_map_id(FindOrAddMap(*map_name));
41 room->set_name(room_name);
42
43 map_container[room_name] = new_id;
44
45 return new_id;
46 } else {
47 return it->second;
48 }
49}
50
51uint64_t Container::FindOrAddPainting(
52 std::optional<std::string> map_name, std::optional<std::string> room_name,
53 std::string painting_name, std::optional<std::string> map_fallback,
54 std::optional<std::string> room_fallback) {
55 if (!map_name) {
56 if (!map_fallback) {
57 std::cout << "No map name provided for " << painting_name << std::endl;
58 map_name = "global";
59 } else {
60 map_name = map_fallback;
61 }
62 }
63
64 if (!room_name) {
65 if (!room_fallback) {
66 std::cout << "No room name provided for " << painting_name << std::endl;
67 room_name = "global";
68 } else {
69 room_name = room_fallback;
70 }
71 }
72
73 auto& room_container =
74 painting_id_by_map_room_painting_names_[*map_name][*room_name];
75 auto it = room_container.find(painting_name);
76 if (it == room_container.end()) {
77 uint64_t new_id = all_objects_.paintings_size();
78 Painting* painting = all_objects_.add_paintings();
79 painting->set_id(new_id);
80 painting->set_room_id(FindOrAddRoom(map_name, *room_name, std::nullopt));
81 painting->set_name(painting_name);
82
83 room_container[painting_name] = new_id;
84
85 return new_id;
86 } else {
87 return it->second;
88 }
89}
90
91uint64_t Container::FindOrAddPort(std::optional<std::string> map_name,
92 std::optional<std::string> room_name,
93 std::string port_name,
94 std::optional<std::string> map_fallback,
95 std::optional<std::string> room_fallback) {
96 if (!map_name) {
97 if (!map_fallback) {
98 std::cout << "No map name provided for " << port_name << std::endl;
99 map_name = "global";
100 } else {
101 map_name = map_fallback;
102 }
103 }
104
105 if (!room_name) {
106 if (!room_fallback) {
107 std::cout << "No room name provided for " << port_name << std::endl;
108 room_name = "global";
109 } else {
110 room_name = room_fallback;
111 }
112 }
113
114 auto& room_container = port_id_by_map_room_port_names_[*map_name][*room_name];
115 auto it = room_container.find(port_name);
116 if (it == room_container.end()) {
117 uint64_t new_id = all_objects_.ports_size();
118 Port* port = all_objects_.add_ports();
119 port->set_id(new_id);
120 port->set_room_id(FindOrAddRoom(map_name, *room_name, std::nullopt));
121 port->set_name(port_name);
122
123 room_container[port_name] = new_id;
124
125 return new_id;
126 } else {
127 return it->second;
128 }
129}
130
131uint64_t Container::FindOrAddPanel(std::optional<std::string> map_name,
132 std::optional<std::string> room_name,
133 std::string panel_name,
134 std::optional<std::string> map_fallback,
135 std::optional<std::string> room_fallback) {
136 if (!map_name) {
137 if (!map_fallback) {
138 std::cout << "No map name provided for " << panel_name << std::endl;
139 map_name = "global";
140 } else {
141 map_name = map_fallback;
142 }
143 }
144
145 if (!room_name) {
146 if (!room_fallback) {
147 std::cout << "No room name provided for " << panel_name << std::endl;
148 room_name = "global";
149 } else {
150 room_name = room_fallback;
151 }
152 }
153
154 auto& room_container =
155 panel_id_by_map_room_panel_names_[*map_name][*room_name];
156 auto it = room_container.find(panel_name);
157 if (it == room_container.end()) {
158 uint64_t new_id = all_objects_.panels_size();
159 Panel* panel = all_objects_.add_panels();
160 panel->set_id(new_id);
161 panel->set_room_id(FindOrAddRoom(map_name, *room_name, std::nullopt));
162 panel->set_name(panel_name);
163
164 room_container[panel_name] = new_id;
165
166 return new_id;
167 } else {
168 return it->second;
169 }
170}
171
172uint64_t Container::FindOrAddDoor(std::optional<std::string> map_name,
173 std::string door_name,
174 std::optional<std::string> map_fallback) {
175 if (!map_name) {
176 if (!map_fallback) {
177 std::cout << "No map name provided for " << door_name << std::endl;
178 map_name = "global";
179 } else {
180 map_name = map_fallback;
181 }
182 }
183
184 auto& map_container = door_id_by_map_door_names_[*map_name];
185 auto it = map_container.find(door_name);
186 if (it == map_container.end()) {
187 uint64_t new_id = all_objects_.doors_size();
188 Door* door = all_objects_.add_doors();
189 door->set_id(new_id);
190 door->set_map_id(FindOrAddMap(*map_name));
191 door->set_name(door_name);
192
193 map_container[door_name] = new_id;
194
195 return new_id;
196 } else {
197 return it->second;
198 }
199}
200
201void Container::AddConnection(const Connection& connection) {
202 *all_objects_.add_connections() = connection;
203}
204
205} // 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 @@
1#ifndef TOOLS_DATAPACKER_CONTAINER_H_
2#define TOOLS_DATAPACKER_CONTAINER_H_
3
4#include <cstdint>
5#include <map>
6#include <optional>
7#include <string>
8
9#include "proto/data.pb.h"
10
11namespace com::fourisland::lingo2_archipelago {
12
13class Container {
14 public:
15 uint64_t FindOrAddMap(std::string map_name);
16
17 uint64_t FindOrAddRoom(std::optional<std::string> map_name,
18 std::string room_name,
19 std::optional<std::string> map_fallback);
20
21 uint64_t FindOrAddPainting(std::optional<std::string> map_name,
22 std::optional<std::string> room_name,
23 std::string painting_name,
24 std::optional<std::string> map_fallback,
25 std::optional<std::string> room_fallback);
26
27 uint64_t FindOrAddPort(std::optional<std::string> map_name,
28 std::optional<std::string> room_name,
29 std::string port_name,
30 std::optional<std::string> map_fallback,
31 std::optional<std::string> room_fallback);
32
33 uint64_t FindOrAddPanel(std::optional<std::string> map_name,
34 std::optional<std::string> room_name,
35 std::string panel_name,
36 std::optional<std::string> map_fallback,
37 std::optional<std::string> room_fallback);
38
39 uint64_t FindOrAddDoor(std::optional<std::string> map_name,
40 std::string door_name,
41 std::optional<std::string> map_fallback);
42
43 void AddConnection(const Connection& connection);
44
45 const AllObjects& all_objects() const { return all_objects_; }
46
47 private:
48 AllObjects all_objects_;
49
50 std::map<std::string, uint64_t> map_id_by_name_;
51 std::map<std::string, std::map<std::string, uint64_t>>
52 room_id_by_map_room_names_;
53 std::map<std::string, std::map<std::string, std::map<std::string, uint64_t>>>
54 painting_id_by_map_room_painting_names_;
55 std::map<std::string, std::map<std::string, std::map<std::string, uint64_t>>>
56 port_id_by_map_room_port_names_;
57 std::map<std::string, std::map<std::string, std::map<std::string, uint64_t>>>
58 panel_id_by_map_room_panel_names_;
59 std::map<std::string, std::map<std::string, uint64_t>>
60 door_id_by_map_door_names_;
61};
62
63} // namespace com::fourisland::lingo2_archipelago
64
65#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 @@
1#include <google/protobuf/message.h>
2#include <google/protobuf/text_format.h>
3
4#include <cstdint>
5#include <filesystem>
6#include <fstream>
1#include <iostream> 7#include <iostream>
8#include <map>
9#include <optional>
10#include <sstream>
2#include <string> 11#include <string>
3 12
4void Run(const std::string& mapdir, const std::string& outputpath) { 13#include "container.h"
14#include "proto/data.pb.h"
15#include "proto/human.pb.h"
16
17namespace com::fourisland::lingo2_archipelago {
18namespace {
19
20template <typename T>
21T ReadMessageFromFile(const std::string& path) {
22 std::ifstream file(path);
23 std::stringstream buffer;
24 buffer << file.rdbuf();
5 25
26 T message;
27 google::protobuf::TextFormat::ParseFromString(buffer.str(), &message);
28
29 return message;
6} 30}
7 31
32class DataPacker {
33 public:
34 DataPacker(const std::string& mapdir, const std::string& outputpath)
35 : mapdir_(mapdir), outputpath_(outputpath) {}
36
37 void Run() {
38 std::filesystem::path datadir_path = mapdir_;
39
40 ProcessConnectionsFile(datadir_path / "connections.txtpb", std::nullopt);
41
42 {
43 std::ofstream outputfile(outputpath_);
44 container_.all_objects().SerializeToOstream(&outputfile);
45 }
46
47 std::string output;
48 google::protobuf::TextFormat::PrintToString(container_.all_objects(),
49 &output);
50 std::cout << output << std::endl;
51 }
52
53 private:
54 void ProcessConnectionsFile(std::filesystem::path path,
55 std::optional<std::string> current_map_name) {
56 if (!std::filesystem::exists(path)) {
57 return;
58 }
59
60 auto connections = ReadMessageFromFile<HumanConnections>(path.string());
61
62 for (const HumanConnection& connection : connections.connections()) {
63 ProcessConnection(connection, current_map_name);
64 }
65 }
66
67 void ProcessConnection(const HumanConnection& human_connection,
68 const std::optional<std::string>& current_map_name) {
69 Connection f_connection;
70
71 if (human_connection.has_from_room()) {
72 f_connection.set_from_room(container_.FindOrAddRoom(
73 std::nullopt, human_connection.from_room(), current_map_name));
74 } else if (human_connection.has_from()) {
75 ProcessSingleConnection(human_connection.from(), current_map_name,
76 f_connection);
77 }
78
79 Connection r_connection;
80 r_connection.set_to_room(f_connection.from_room());
81
82 if (human_connection.has_to_room()) {
83 r_connection.set_to_room(container_.FindOrAddRoom(
84 std::nullopt, human_connection.to_room(), current_map_name));
85 } else if (human_connection.has_to()) {
86 ProcessSingleConnection(human_connection.to(), current_map_name,
87 r_connection);
88 }
89
90 f_connection.set_to_room(r_connection.from_room());
91
92 if (human_connection.has_door()) {
93 std::optional<std::string> map_name =
94 human_connection.door().has_map()
95 ? std::optional<std::string>(human_connection.door().map())
96 : std::nullopt;
97 uint64_t door_id = container_.FindOrAddDoor(
98 map_name, human_connection.door().name(), current_map_name);
99 f_connection.set_required_door(door_id);
100 r_connection.set_required_door(door_id);
101 }
102
103 container_.AddConnection(f_connection);
104 if (!human_connection.oneway()) {
105 container_.AddConnection(r_connection);
106 }
107 }
108
109 void ProcessSingleConnection(
110 const HumanConnection::Endpoint& endpoint,
111 const std::optional<std::string>& current_map_name,
112 Connection& connection) {
113 if (endpoint.has_room()) {
114 std::optional<std::string> map_name =
115 endpoint.room().has_map()
116 ? std::optional<std::string>(endpoint.room().map())
117 : std::nullopt;
118 connection.set_from_room(container_.FindOrAddRoom(
119 map_name, endpoint.room().name(), current_map_name));
120 } else if (endpoint.has_painting()) {
121 std::optional<std::string> map_name =
122 endpoint.painting().has_map()
123 ? std::optional<std::string>(endpoint.painting().map())
124 : std::nullopt;
125
126 std::string room_name;
127 if (!endpoint.painting().has_room()) {
128 std::cout << "Missing room name for painting "
129 << endpoint.painting().name() << std::endl;
130 room_name = "default";
131 } else {
132 room_name = endpoint.painting().room();
133 }
134
135 connection.set_from_room(
136 container_.FindOrAddRoom(map_name, room_name, current_map_name));
137 connection.set_painting(container_.FindOrAddPainting(
138 map_name, room_name, endpoint.painting().name(), current_map_name,
139 std::nullopt));
140 } else if (endpoint.has_port()) {
141 std::optional<std::string> map_name =
142 endpoint.port().has_map()
143 ? std::optional<std::string>(endpoint.port().map())
144 : std::nullopt;
145
146 std::string room_name;
147 if (!endpoint.port().has_room()) {
148 std::cout << "Missing room name for port " << endpoint.port().name()
149 << std::endl;
150 room_name = "default";
151 } else {
152 room_name = endpoint.port().room();
153 }
154
155 connection.set_from_room(
156 container_.FindOrAddRoom(map_name, room_name, current_map_name));
157 connection.set_port(
158 container_.FindOrAddPort(map_name, room_name, endpoint.port().name(),
159 current_map_name, std::nullopt));
160 } else if (endpoint.has_panel()) {
161 std::optional<std::string> map_name =
162 endpoint.panel().has_map()
163 ? std::optional<std::string>(endpoint.panel().map())
164 : std::nullopt;
165
166 std::string room_name;
167 if (!endpoint.panel().has_room()) {
168 std::cout << "Missing room name for panel " << endpoint.panel().name()
169 << std::endl;
170 room_name = "default";
171 } else {
172 room_name = endpoint.panel().room();
173 }
174
175 connection.set_from_room(
176 container_.FindOrAddRoom(map_name, room_name, current_map_name));
177 connection.mutable_panel()->set_panel(container_.FindOrAddPanel(
178 map_name, room_name, endpoint.panel().name(), current_map_name,
179 std::nullopt));
180 if (endpoint.panel().has_answer()) {
181 connection.mutable_panel()->set_answer(endpoint.panel().answer());
182 }
183 }
184 }
185
186 std::string mapdir_;
187 std::string outputpath_;
188
189 Container container_;
190};
191
192} // namespace
193} // namespace com::fourisland::lingo2_archipelago
194
8int main(int argc, char** argv) { 195int main(int argc, char** argv) {
9 if (argc != 3) { 196 if (argc != 3) {
10 std::cout << "Incorrect argument count." << std::endl; 197 std::cout << "Incorrect argument count." << std::endl;
11 std::cout << "Usage: datapacker [path to map directory] [output file]" << std::endl; 198 std::cout << "Usage: datapacker [path to map directory] [output file]"
199 << std::endl;
12 return 1; 200 return 1;
13 } 201 }
14 202
15 std::string mapdir = argv[1]; 203 std::string mapdir = argv[1];
16 std::string outputpath = argv[2]; 204 std::string outputpath = argv[2];
17 205
18 Run(mapdir, outputpath); 206 com::fourisland::lingo2_archipelago::DataPacker data_packer(mapdir,
207 outputpath);
208 data_packer.Run();
19 209
20 return 0; 210 return 0;
21} 211}