yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
atlas_json.cc
Go to the documentation of this file.
2
3#include <cmath>
4
5#include "absl/strings/str_format.h"
6#include "nlohmann/json.hpp"
7
8namespace yaze::zelda3::atlas {
9
10namespace {
11
12using Json = nlohmann::ordered_json;
13
14std::string Hex(int id) {
15 return absl::StrFormat("0x%02X", id);
16}
17
18Json HexOrNull(int id) {
19 return id >= 0 ? Json(Hex(id)) : Json(nullptr);
20}
21
22Json RoomList(const std::vector<int>& rooms) {
23 Json list = Json::array();
24 for (int room : rooms) {
25 list.push_back(Hex(room));
26 }
27 return list;
28}
29
30Json LinkJson(const AtlasLink& link, bool outgoing) {
31 Json out;
32 out["kind"] = LinkKindName(link.kind);
33 if (!link.style.empty()) {
34 out["style"] = link.style;
35 }
36 if (outgoing) {
37 out["to"] = HexOrNull(link.to);
38 out["cross_area"] = link.cross_area;
39 }
40 if (link.entrance >= 0) {
41 out["entrance"] = Hex(link.entrance);
42 }
43 if (link.ow_map >= 0) {
44 out["ow"] = Hex(link.ow_map);
45 }
46 switch (link.kind) {
48 out["spawn"] = link.index;
49 break;
52 out["slot"] = link.index;
53 break;
55 out["n"] = link.index;
56 break;
57 default:
58 break;
59 }
60 if (!link.label.empty()) {
61 out["label"] = link.label;
62 }
63 if (!link.note.empty()) {
64 out["note"] = link.note;
65 }
66 out["source"] = link.origin.ToString();
67 return out;
68}
69
70} // namespace
71
72std::string DungeonAtlasToJson(const DungeonAtlas& atlas,
73 const DungeonAtlasJsonContext& context,
74 int indent) {
75 Json root;
76 root["schema"] = kDungeonAtlasJsonSchema;
77 root["rom"] = {{"name", atlas.rom.name},
78 {"sha1", atlas.rom.sha1},
79 {"size", atlas.rom.size}};
80 root["project"] =
81 context.project.empty() ? Json(nullptr) : Json(context.project);
82 if (!context.generator.empty()) {
83 root["generator"] = context.generator;
84 }
85 root["title"] = atlas.title;
86 root["annotations"] = atlas.annotation_files;
87 root["symbols"] = atlas.symbols.empty() ? Json(nullptr) : Json(atlas.symbols);
88 root["owners_source"] =
89 atlas.owners_from_project ? "project" : "derived_from_entrances";
90 root["expanded_entrance_tables"] = atlas.expanded_entrance_tables;
91 root["counts"] = {{"free", atlas.counts.free},
92 {"reclaimable", atlas.counts.reclaimable},
93 {"in_use", atlas.counts.in_use},
94 {"orphan", atlas.counts.orphan},
95 {"reserved", atlas.counts.reserved},
96 {"interior", atlas.counts.interior},
97 {"door_edges", atlas.edges.size()}};
98
99 Json areas = Json::array();
100 for (const auto& area : atlas.areas) {
101 Json out;
102 out["key"] = area.key;
103 out["code"] = area.code;
104 out["name"] = area.name;
105 out["kind"] = area.kind;
106 if (!area.owner.empty()) {
107 out["owner"] = area.owner;
108 }
109 out["color"] = area.color.Hex();
110 out["rooms"] = area.rooms;
111 out["source"] = area.origin.ToString();
112 out["color_source"] = area.color_origin.ToString();
113 areas.push_back(std::move(out));
114 }
115 root["areas"] = std::move(areas);
116
117 Json plans = Json::array();
118 for (const auto& plan : atlas.plans) {
119 Json out;
120 out["key"] = plan.key;
121 out["label"] = plan.label;
122 out["name"] = plan.name;
123 out["status"] = plan.status;
124 out["color"] = plan.has_color ? Json(plan.color.Hex()) : Json(nullptr);
125 out["rooms"] = RoomList(plan.rooms);
126 if (!plan.note.empty()) {
127 out["note"] = plan.note;
128 }
129 out["source"] = plan.origin.ToString();
130 plans.push_back(std::move(out));
131 }
132 root["plans"] = std::move(plans);
133
134 Json rooms = Json::array();
135 for (const auto& room : atlas.rooms) {
136 Json out;
137 out["room"] = Hex(room.room_id);
138 out["area"] = room.area;
139 out["area_source"] = room.area_origin.ToString();
140 out["owner"] = room.owner.empty() ? Json(nullptr) : Json(room.owner);
141 out["owner_name"] = room.owner_name;
142 out["name"] = room.name;
143 out["name_source"] =
144 room.name.empty() ? Json(nullptr) : Json(room.name_origin.ToString());
145 if (!room.note.empty()) {
146 out["note"] = room.note;
147 }
148 out["status"] = RoomStatusName(room.status);
149 out["status_source"] = room.status_origin.ToString();
150 out["reached"] = room.reached;
151 out["empty"] = room.empty;
152 out["interior"] = room.interior;
153 out["objects"] = room.objects;
154 out["sprites"] = room.sprites;
155 out["vanilla_similarity"] =
156 room.vanilla_similarity < 0.0f
157 ? Json(nullptr)
158 : Json(std::round(room.vanilla_similarity * 100.0) / 100.0);
159 out["tags"] = {Hex(room.tag1), Hex(room.tag2)};
160 out["blockset"] = room.blockset;
161 out["pit_damage"] = room.pit_damage;
162 out["plans"] = room.plans;
163 out["reasons"] = room.reasons;
164 Json doors = Json::array();
165 for (const auto& door : room.doors) {
166 doors.push_back({{"wall", std::string(1, door.wall)},
167 {"pos", door.pos},
168 {"type", Hex(door.type)},
169 {"type_name", door.type_name},
170 {"category", DoorCategoryName(door.category)}});
171 }
172 out["doors"] = std::move(doors);
173 Json links_out = Json::array();
174 for (const auto& link : room.links_out) {
175 links_out.push_back(LinkJson(link, /*outgoing=*/true));
176 }
177 out["links_out"] = std::move(links_out);
178 Json links_in = Json::array();
179 for (const auto& link : room.links_in) {
180 links_in.push_back(LinkJson(link, /*outgoing=*/false));
181 }
182 out["links_in"] = std::move(links_in);
183 out["badges"] = {{"k_chest", room.badges.k_chest},
184 {"c", room.badges.c},
185 {"m", room.badges.m},
186 {"bk_chest", room.badges.bk_chest},
187 {"big_chest", room.badges.big_chest},
188 {"other", room.badges.other},
189 {"k_pot", room.badges.k_pot},
190 {"k_drop", room.badges.k_drop},
191 {"bk_drop", room.badges.bk_drop}};
192 rooms.push_back(std::move(out));
193 }
194 root["rooms"] = std::move(rooms);
195
196 Json edges = Json::array();
197 for (const auto& edge : atlas.edges) {
198 edges.push_back({{"a", Hex(edge.a)},
199 {"b", Hex(edge.b)},
200 {"dir", std::string(1, edge.dir)},
201 {"pos", edge.pos},
202 {"category", DoorCategoryName(edge.category)},
203 {"sides", edge.both_sides ? "both" : "a"},
204 {"one_sided_type", edge.one_sided_type},
205 {"types", edge.types}});
206 }
207 root["edges"] = std::move(edges);
208
209 Json key_table = Json::array();
210 for (const auto& row : atlas.key_table) {
211 key_table.push_back({{"area", row.area},
212 {"k_chest", row.k_chest},
213 {"k_pot", row.k_pot},
214 {"k_drop", row.k_drop},
215 {"bk", row.bk},
216 {"bc", row.bc},
217 {"c", row.c},
218 {"m", row.m}});
219 }
220 root["key_table"] = std::move(key_table);
221 root["legend_notes"] = atlas.legend_notes;
222 root["warnings"] = atlas.warnings;
223 return root.dump(indent);
224}
225
226} // namespace yaze::zelda3::atlas
static Json array()
Definition json.h:35
bool empty() const
Definition json.h:62
std::string dump(int=-1, char=' ', bool=false, int=0) const
Definition json.h:91
Json LinkJson(const AtlasLink &link, bool outgoing)
Definition atlas_json.cc:30
Json RoomList(const std::vector< int > &rooms)
Definition atlas_json.cc:22
const char * RoomStatusName(RoomStatus status)
const char * LinkKindName(LinkKind kind)
std::string DungeonAtlasToJson(const DungeonAtlas &atlas, const DungeonAtlasJsonContext &context, int indent)
Definition atlas_json.cc:72
constexpr char kDungeonAtlasJsonSchema[]
Definition atlas_json.h:15
const char * DoorCategoryName(DoorCategory category)
std::vector< AtlasPlan > plans
std::vector< DoorEdge > edges
std::vector< AtlasKeyTableRow > key_table
std::vector< AtlasArea > areas
std::vector< std::string > annotation_files
std::vector< std::string > warnings
std::vector< DungeonAtlasRoom > rooms
std::vector< std::string > legend_notes