2019-02-02 20:22:41 +01:00
|
|
|
// mapjson.cpp
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
using std::cout; using std::endl;
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
using std::string;
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
using std::vector;
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
using std::sort; using std::find;
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
using std::map;
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
using std::ofstream; using std::ifstream;
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
using std::ostringstream;
|
|
|
|
|
|
|
|
#include <limits>
|
|
|
|
using std::numeric_limits;
|
|
|
|
|
|
|
|
#include "json11.h"
|
|
|
|
using json11::Json;
|
|
|
|
|
|
|
|
#include "mapjson.h"
|
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
string version;
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
string read_text_file(string filepath) {
|
|
|
|
ifstream in_file(filepath);
|
|
|
|
|
|
|
|
if (!in_file.is_open())
|
|
|
|
FATAL_ERROR("Cannot open file %s for reading.\n", filepath.c_str());
|
|
|
|
|
|
|
|
string text;
|
|
|
|
|
|
|
|
in_file.seekg(0, std::ios::end);
|
|
|
|
text.resize(in_file.tellg());
|
|
|
|
|
|
|
|
in_file.seekg(0, std::ios::beg);
|
|
|
|
in_file.read(&text[0], text.size());
|
|
|
|
|
|
|
|
in_file.close();
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
void write_text_file(string filepath, string text) {
|
2019-02-05 00:28:45 +01:00
|
|
|
ofstream out_file(filepath, std::ofstream::binary);
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
if (!out_file.is_open())
|
|
|
|
FATAL_ERROR("Cannot open file %s for writing.\n", filepath.c_str());
|
|
|
|
|
|
|
|
out_file << text;
|
|
|
|
|
|
|
|
out_file.close();
|
|
|
|
}
|
|
|
|
|
2023-01-17 22:11:15 +01:00
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
string json_to_string(const Json &data, const string &field = "", bool silent = false) {
|
2023-01-17 22:11:15 +01:00
|
|
|
const Json value = !field.empty() ? data[field] : data;
|
2023-01-17 21:25:39 +01:00
|
|
|
string output = "";
|
|
|
|
switch (value.type()) {
|
|
|
|
case Json::Type::STRING:
|
|
|
|
output = value.string_value();
|
|
|
|
break;
|
|
|
|
case Json::Type::NUMBER:
|
|
|
|
output = std::to_string(value.int_value());
|
|
|
|
break;
|
|
|
|
case Json::Type::BOOL:
|
|
|
|
output = value.bool_value() ? "TRUE" : "FALSE";
|
|
|
|
break;
|
2023-04-21 09:20:36 +02:00
|
|
|
case Json::Type::NUL:
|
|
|
|
output = "";
|
|
|
|
break;
|
2023-01-17 22:11:15 +01:00
|
|
|
default:{
|
2023-02-08 18:10:17 +01:00
|
|
|
if (!silent) {
|
|
|
|
string s = !field.empty() ? ("Value for '" + field + "'") : "JSON field";
|
|
|
|
FATAL_ERROR("%s is unexpected type; expected string, number, or bool.\n", s.c_str());
|
|
|
|
}
|
2023-01-17 22:11:15 +01:00
|
|
|
}
|
2023-01-17 21:25:39 +01:00
|
|
|
}
|
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
if (!silent && output.empty()) {
|
2023-01-17 22:11:15 +01:00
|
|
|
string s = !field.empty() ? ("Value for '" + field + "'") : "JSON field";
|
|
|
|
FATAL_ERROR("%s cannot be empty.\n", s.c_str());
|
|
|
|
}
|
2023-01-17 21:25:39 +01:00
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
string generate_map_header_text(Json map_data, Json layouts_data) {
|
2023-01-17 22:11:15 +01:00
|
|
|
string map_layout_id = json_to_string(map_data, "layout");
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
vector<Json> matched;
|
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
for (auto &layout : layouts_data["layouts"].array_items()) {
|
|
|
|
if (map_layout_id == json_to_string(layout, "id", true))
|
|
|
|
matched.push_back(layout);
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (matched.size() != 1)
|
|
|
|
FATAL_ERROR("Failed to find matching layout for %s.\n", map_layout_id.c_str());
|
|
|
|
|
|
|
|
Json layout = matched[0];
|
|
|
|
|
|
|
|
ostringstream text;
|
|
|
|
|
2023-01-17 22:11:15 +01:00
|
|
|
string mapName = json_to_string(map_data, "name");
|
2020-07-24 09:43:37 +02:00
|
|
|
|
2023-01-17 21:40:39 +01:00
|
|
|
text << "@\n@ DO NOT MODIFY THIS FILE! It is auto-generated from data/maps/" << mapName << "/map.json\n@\n\n";
|
2020-07-24 09:43:37 +02:00
|
|
|
|
2023-01-17 21:40:39 +01:00
|
|
|
text << mapName << ":\n"
|
2023-01-17 22:11:15 +01:00
|
|
|
<< "\t.4byte " << json_to_string(layout, "name") << "\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
if (map_data.object_items().find("shared_events_map") != map_data.object_items().end())
|
2023-01-17 22:11:15 +01:00
|
|
|
text << "\t.4byte " << json_to_string(map_data, "shared_events_map") << "_MapEvents\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
else
|
2023-01-17 21:40:39 +01:00
|
|
|
text << "\t.4byte " << mapName << "_MapEvents\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
if (map_data.object_items().find("shared_scripts_map") != map_data.object_items().end())
|
2023-01-17 22:11:15 +01:00
|
|
|
text << "\t.4byte " << json_to_string(map_data, "shared_scripts_map") << "_MapScripts\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
else
|
2023-01-17 21:40:39 +01:00
|
|
|
text << "\t.4byte " << mapName << "_MapScripts\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
if (map_data.object_items().find("connections") != map_data.object_items().end()
|
2023-02-08 18:10:17 +01:00
|
|
|
&& map_data["connections"].array_items().size() > 0 && json_to_string(map_data, "connections_no_include", true) != "TRUE")
|
2023-01-17 21:40:39 +01:00
|
|
|
text << "\t.4byte " << mapName << "_MapConnections\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
else
|
2023-02-08 18:10:17 +01:00
|
|
|
text << "\t.4byte NULL\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
|
2023-01-17 22:11:15 +01:00
|
|
|
text << "\t.2byte " << json_to_string(map_data, "music") << "\n"
|
|
|
|
<< "\t.2byte " << json_to_string(layout, "id") << "\n"
|
|
|
|
<< "\t.byte " << json_to_string(map_data, "region_map_section") << "\n"
|
|
|
|
<< "\t.byte " << json_to_string(map_data, "requires_flash") << "\n"
|
|
|
|
<< "\t.byte " << json_to_string(map_data, "weather") << "\n"
|
2023-02-08 18:10:17 +01:00
|
|
|
<< "\t.byte " << json_to_string(map_data, "map_type") << "\n";
|
|
|
|
|
|
|
|
if (version != "firered")
|
|
|
|
text << "\t.2byte 0\n";
|
2019-02-05 00:28:45 +01:00
|
|
|
|
|
|
|
if (version == "ruby")
|
2023-01-17 22:11:15 +01:00
|
|
|
text << "\t.byte " << json_to_string(map_data, "show_map_name") << "\n";
|
2023-02-08 18:10:17 +01:00
|
|
|
else if (version == "emerald" || version == "firered")
|
2019-02-05 00:28:45 +01:00
|
|
|
text << "\tmap_header_flags "
|
2023-01-17 22:11:15 +01:00
|
|
|
<< "allow_cycling=" << json_to_string(map_data, "allow_cycling") << ", "
|
|
|
|
<< "allow_escaping=" << json_to_string(map_data, "allow_escaping") << ", "
|
|
|
|
<< "allow_running=" << json_to_string(map_data, "allow_running") << ", "
|
|
|
|
<< "show_map_name=" << json_to_string(map_data, "show_map_name") << "\n";
|
2019-02-05 00:28:45 +01:00
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
if (version == "firered")
|
|
|
|
text << "\t.byte " << json_to_string(map_data, "floor_number") << "\n";
|
|
|
|
|
2023-01-17 22:11:15 +01:00
|
|
|
text << "\t.byte " << json_to_string(map_data, "battle_scene") << "\n\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
string generate_map_connections_text(Json map_data) {
|
|
|
|
if (map_data["connections"] == Json())
|
|
|
|
return string("\n");
|
|
|
|
|
|
|
|
ostringstream text;
|
|
|
|
|
2023-01-17 22:11:15 +01:00
|
|
|
string mapName = json_to_string(map_data, "name");
|
2020-07-24 09:43:37 +02:00
|
|
|
|
2023-01-17 21:40:39 +01:00
|
|
|
text << "@\n@ DO NOT MODIFY THIS FILE! It is auto-generated from data/maps/" << mapName << "/map.json\n@\n\n";
|
2020-07-24 09:43:37 +02:00
|
|
|
|
2023-01-17 21:40:39 +01:00
|
|
|
text << mapName << "_MapConnectionsList:\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
for (auto &connection : map_data["connections"].array_items()) {
|
|
|
|
text << "\tconnection "
|
2023-01-17 22:11:15 +01:00
|
|
|
<< json_to_string(connection, "direction") << ", "
|
|
|
|
<< json_to_string(connection, "offset") << ", "
|
|
|
|
<< json_to_string(connection, "map") << "\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
|
2023-01-17 21:40:39 +01:00
|
|
|
text << "\n" << mapName << "_MapConnections:\n"
|
2019-02-02 20:22:41 +01:00
|
|
|
<< "\t.4byte " << map_data["connections"].array_items().size() << "\n"
|
2023-01-17 21:40:39 +01:00
|
|
|
<< "\t.4byte " << mapName << "_MapConnectionsList\n\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
string generate_map_events_text(Json map_data) {
|
|
|
|
if (map_data.object_items().find("shared_events_map") != map_data.object_items().end())
|
|
|
|
return string("\n");
|
|
|
|
|
|
|
|
ostringstream text;
|
|
|
|
|
2023-01-17 22:11:15 +01:00
|
|
|
string mapName = json_to_string(map_data, "name");
|
2023-01-17 21:40:39 +01:00
|
|
|
|
|
|
|
text << "@\n@ DO NOT MODIFY THIS FILE! It is auto-generated from data/maps/" << mapName << "/map.json\n@\n\n";
|
2020-07-24 09:43:37 +02:00
|
|
|
|
2019-02-02 20:22:41 +01:00
|
|
|
string objects_label, warps_label, coords_label, bgs_label;
|
|
|
|
|
|
|
|
if (map_data["object_events"].array_items().size() > 0) {
|
2023-01-17 21:40:39 +01:00
|
|
|
objects_label = mapName + "_ObjectEvents";
|
2019-02-02 20:22:41 +01:00
|
|
|
text << objects_label << ":\n";
|
2019-02-05 00:28:45 +01:00
|
|
|
for (unsigned int i = 0; i < map_data["object_events"].array_items().size(); i++) {
|
2019-02-02 20:22:41 +01:00
|
|
|
auto obj_event = map_data["object_events"].array_items()[i];
|
2023-02-08 18:10:17 +01:00
|
|
|
string type = json_to_string(obj_event, "type", true);
|
|
|
|
|
|
|
|
// If no type field is present, assume it's a regular object event.
|
|
|
|
if (type == "" || type == "object") {
|
|
|
|
text << "\tobject_event " << i + 1 << ", "
|
2023-02-08 19:11:10 +01:00
|
|
|
<< json_to_string(obj_event, "graphics_id") << ", "
|
2023-02-08 18:10:17 +01:00
|
|
|
<< json_to_string(obj_event, "x") << ", "
|
|
|
|
<< json_to_string(obj_event, "y") << ", "
|
|
|
|
<< json_to_string(obj_event, "elevation") << ", "
|
|
|
|
<< json_to_string(obj_event, "movement_type") << ", "
|
|
|
|
<< json_to_string(obj_event, "movement_range_x") << ", "
|
|
|
|
<< json_to_string(obj_event, "movement_range_y") << ", "
|
|
|
|
<< json_to_string(obj_event, "trainer_type") << ", "
|
|
|
|
<< json_to_string(obj_event, "trainer_sight_or_berry_tree_id") << ", "
|
|
|
|
<< json_to_string(obj_event, "script") << ", "
|
|
|
|
<< json_to_string(obj_event, "flag") << "\n";
|
|
|
|
} else if (type == "clone") {
|
|
|
|
text << "\tclone_event " << i + 1 << ", "
|
|
|
|
<< json_to_string(obj_event, "graphics_id") << ", "
|
|
|
|
<< json_to_string(obj_event, "x") << ", "
|
|
|
|
<< json_to_string(obj_event, "y") << ", "
|
|
|
|
<< json_to_string(obj_event, "target_local_id") << ", "
|
|
|
|
<< json_to_string(obj_event, "target_map") << "\n";
|
2023-02-08 18:52:28 +01:00
|
|
|
} else {
|
|
|
|
FATAL_ERROR("Unknown object event type '%s'. Expected 'object' or 'clone'.\n", type.c_str());
|
2023-02-08 18:10:17 +01:00
|
|
|
}
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
text << "\n";
|
|
|
|
} else {
|
2023-02-08 18:10:17 +01:00
|
|
|
objects_label = "NULL";
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (map_data["warp_events"].array_items().size() > 0) {
|
2023-01-17 21:40:39 +01:00
|
|
|
warps_label = mapName + "_MapWarps";
|
2019-02-02 20:22:41 +01:00
|
|
|
text << warps_label << ":\n";
|
|
|
|
for (auto &warp_event : map_data["warp_events"].array_items()) {
|
|
|
|
text << "\twarp_def "
|
2023-01-17 22:11:15 +01:00
|
|
|
<< json_to_string(warp_event, "x") << ", "
|
|
|
|
<< json_to_string(warp_event, "y") << ", "
|
|
|
|
<< json_to_string(warp_event, "elevation") << ", "
|
|
|
|
<< json_to_string(warp_event, "dest_warp_id") << ", "
|
|
|
|
<< json_to_string(warp_event, "dest_map") << "\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
text << "\n";
|
|
|
|
} else {
|
2023-02-08 18:10:17 +01:00
|
|
|
warps_label = "NULL";
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (map_data["coord_events"].array_items().size() > 0) {
|
2023-01-17 21:40:39 +01:00
|
|
|
coords_label = mapName + "_MapCoordEvents";
|
2019-02-02 20:22:41 +01:00
|
|
|
text << coords_label << ":\n";
|
|
|
|
for (auto &coord_event : map_data["coord_events"].array_items()) {
|
2023-02-08 18:10:17 +01:00
|
|
|
string type = json_to_string(coord_event, "type");
|
|
|
|
if (type == "trigger") {
|
2019-02-02 20:22:41 +01:00
|
|
|
text << "\tcoord_event "
|
2023-01-17 22:11:15 +01:00
|
|
|
<< json_to_string(coord_event, "x") << ", "
|
|
|
|
<< json_to_string(coord_event, "y") << ", "
|
|
|
|
<< json_to_string(coord_event, "elevation") << ", "
|
|
|
|
<< json_to_string(coord_event, "var") << ", "
|
|
|
|
<< json_to_string(coord_event, "var_value") << ", "
|
|
|
|
<< json_to_string(coord_event, "script") << "\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
2023-02-08 18:10:17 +01:00
|
|
|
else if (type == "weather") {
|
2019-02-02 20:22:41 +01:00
|
|
|
text << "\tcoord_weather_event "
|
2023-01-17 22:11:15 +01:00
|
|
|
<< json_to_string(coord_event, "x") << ", "
|
|
|
|
<< json_to_string(coord_event, "y") << ", "
|
|
|
|
<< json_to_string(coord_event, "elevation") << ", "
|
|
|
|
<< json_to_string(coord_event, "weather") << "\n";
|
2023-02-08 18:52:28 +01:00
|
|
|
} else {
|
|
|
|
FATAL_ERROR("Unknown coord event type '%s'. Expected 'trigger' or 'weather'.\n", type.c_str());
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
text << "\n";
|
|
|
|
} else {
|
2023-02-08 18:10:17 +01:00
|
|
|
coords_label = "NULL";
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (map_data["bg_events"].array_items().size() > 0) {
|
2023-01-17 21:40:39 +01:00
|
|
|
bgs_label = mapName + "_MapBGEvents";
|
2019-02-02 20:22:41 +01:00
|
|
|
text << bgs_label << ":\n";
|
|
|
|
for (auto &bg_event : map_data["bg_events"].array_items()) {
|
2023-02-08 18:10:17 +01:00
|
|
|
string type = json_to_string(bg_event, "type");
|
|
|
|
if (type == "sign") {
|
2022-01-24 00:51:56 +01:00
|
|
|
text << "\tbg_sign_event "
|
2023-01-17 22:11:15 +01:00
|
|
|
<< json_to_string(bg_event, "x") << ", "
|
|
|
|
<< json_to_string(bg_event, "y") << ", "
|
|
|
|
<< json_to_string(bg_event, "elevation") << ", "
|
|
|
|
<< json_to_string(bg_event, "player_facing_dir") << ", "
|
|
|
|
<< json_to_string(bg_event, "script") << "\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
2023-02-08 18:10:17 +01:00
|
|
|
else if (type == "hidden_item") {
|
2019-02-02 20:22:41 +01:00
|
|
|
text << "\tbg_hidden_item_event "
|
2023-01-17 22:11:15 +01:00
|
|
|
<< json_to_string(bg_event, "x") << ", "
|
|
|
|
<< json_to_string(bg_event, "y") << ", "
|
|
|
|
<< json_to_string(bg_event, "elevation") << ", "
|
|
|
|
<< json_to_string(bg_event, "item") << ", "
|
2023-02-08 18:10:17 +01:00
|
|
|
<< json_to_string(bg_event, "flag");
|
|
|
|
if (version == "firered") {
|
|
|
|
text << ", "
|
|
|
|
<< json_to_string(bg_event, "quantity") << ", "
|
|
|
|
<< json_to_string(bg_event, "underfoot");
|
|
|
|
}
|
|
|
|
text << "\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
2023-02-08 18:10:17 +01:00
|
|
|
else if (type == "secret_base") {
|
2019-02-02 20:22:41 +01:00
|
|
|
text << "\tbg_secret_base_event "
|
2023-01-17 22:11:15 +01:00
|
|
|
<< json_to_string(bg_event, "x") << ", "
|
|
|
|
<< json_to_string(bg_event, "y") << ", "
|
|
|
|
<< json_to_string(bg_event, "elevation") << ", "
|
|
|
|
<< json_to_string(bg_event, "secret_base_id") << "\n";
|
2023-02-08 18:52:28 +01:00
|
|
|
} else {
|
|
|
|
FATAL_ERROR("Unknown bg event type '%s'. Expected 'sign', 'hidden_item', or 'secret_base'.\n", type.c_str());
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
text << "\n";
|
|
|
|
} else {
|
2023-02-08 18:10:17 +01:00
|
|
|
bgs_label = "NULL";
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
|
2023-01-17 21:40:39 +01:00
|
|
|
text << mapName << "_MapEvents::\n"
|
2019-02-02 20:22:41 +01:00
|
|
|
<< "\tmap_events " << objects_label << ", " << warps_label << ", "
|
|
|
|
<< coords_label << ", " << bgs_label << "\n\n";
|
|
|
|
|
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
string get_directory_name(string filename) {
|
|
|
|
size_t dir_pos = filename.find_last_of("/\\");
|
|
|
|
|
|
|
|
return filename.substr(0, dir_pos + 1);
|
|
|
|
}
|
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
void process_map(string map_filepath, string layouts_filepath) {
|
2019-02-02 20:22:41 +01:00
|
|
|
string mapdata_err, layouts_err;
|
|
|
|
|
|
|
|
string mapdata_json_text = read_text_file(map_filepath);
|
|
|
|
string layouts_json_text = read_text_file(layouts_filepath);
|
|
|
|
|
|
|
|
Json map_data = Json::parse(mapdata_json_text, mapdata_err);
|
|
|
|
if (map_data == Json())
|
|
|
|
FATAL_ERROR("%s\n", mapdata_err.c_str());
|
|
|
|
|
|
|
|
Json layouts_data = Json::parse(layouts_json_text, layouts_err);
|
|
|
|
if (layouts_data == Json())
|
|
|
|
FATAL_ERROR("%s\n", layouts_err.c_str());
|
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
string header_text = generate_map_header_text(map_data, layouts_data);
|
2019-02-02 20:22:41 +01:00
|
|
|
string events_text = generate_map_events_text(map_data);
|
|
|
|
string connections_text = generate_map_connections_text(map_data);
|
|
|
|
|
|
|
|
string files_dir = get_directory_name(map_filepath);
|
|
|
|
write_text_file(files_dir + "header.inc", header_text);
|
|
|
|
write_text_file(files_dir + "events.inc", events_text);
|
|
|
|
write_text_file(files_dir + "connections.inc", connections_text);
|
|
|
|
}
|
|
|
|
|
|
|
|
string generate_groups_text(Json groups_data) {
|
|
|
|
ostringstream text;
|
|
|
|
|
2020-07-24 09:43:37 +02:00
|
|
|
text << "@\n@ DO NOT MODIFY THIS FILE! It is auto-generated from data/maps/map_groups.json\n@\n\n";
|
|
|
|
|
2019-02-02 20:22:41 +01:00
|
|
|
for (auto &key : groups_data["group_order"].array_items()) {
|
2023-01-17 21:25:39 +01:00
|
|
|
string group = json_to_string(key);
|
2019-02-02 20:22:41 +01:00
|
|
|
text << group << "::\n";
|
|
|
|
auto maps = groups_data[group].array_items();
|
|
|
|
for (Json &map_name : maps)
|
2023-01-17 21:25:39 +01:00
|
|
|
text << "\t.4byte " << json_to_string(map_name) << "\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
text << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
text << "\t.align 2\n" << "gMapGroups::\n";
|
|
|
|
for (auto &group : groups_data["group_order"].array_items())
|
2023-01-17 21:25:39 +01:00
|
|
|
text << "\t.4byte " << json_to_string(group) << "\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
text << "\n";
|
|
|
|
|
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
string generate_connections_text(Json groups_data) {
|
|
|
|
vector<Json> map_names;
|
|
|
|
|
|
|
|
for (auto &group : groups_data["group_order"].array_items())
|
2023-01-17 21:25:39 +01:00
|
|
|
for (auto map_name : groups_data[json_to_string(group)].array_items())
|
2019-02-02 20:22:41 +01:00
|
|
|
map_names.push_back(map_name);
|
|
|
|
|
|
|
|
vector<Json> connections_include_order = groups_data["connections_include_order"].array_items();
|
|
|
|
|
|
|
|
if (connections_include_order.size() > 0)
|
|
|
|
sort(map_names.begin(), map_names.end(), [connections_include_order](const Json &a, const Json &b) {
|
|
|
|
auto iter_a = find(connections_include_order.begin(), connections_include_order.end(), a);
|
|
|
|
if (iter_a == connections_include_order.end())
|
|
|
|
iter_a = connections_include_order.begin() + numeric_limits<int>::max();
|
|
|
|
auto iter_b = find(connections_include_order.begin(), connections_include_order.end(), b);
|
|
|
|
if (iter_b == connections_include_order.end())
|
|
|
|
iter_b = connections_include_order.begin() + numeric_limits<int>::max();
|
|
|
|
return iter_a < iter_b;
|
|
|
|
});
|
|
|
|
|
|
|
|
ostringstream text;
|
|
|
|
|
2020-07-24 09:43:37 +02:00
|
|
|
text << "@\n@ DO NOT MODIFY THIS FILE! It is auto-generated from data/maps/map_groups.json\n@\n\n";
|
|
|
|
|
2019-02-02 20:22:41 +01:00
|
|
|
for (Json map_name : map_names)
|
2023-01-17 21:25:39 +01:00
|
|
|
text << "\t.include \"data/maps/" << json_to_string(map_name) << "/connections.inc\"\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
string generate_headers_text(Json groups_data) {
|
|
|
|
vector<string> map_names;
|
|
|
|
|
|
|
|
for (auto &group : groups_data["group_order"].array_items())
|
2023-01-17 21:25:39 +01:00
|
|
|
for (auto map_name : groups_data[json_to_string(group)].array_items())
|
|
|
|
map_names.push_back(json_to_string(map_name));
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
ostringstream text;
|
|
|
|
|
2020-07-24 09:43:37 +02:00
|
|
|
text << "@\n@ DO NOT MODIFY THIS FILE! It is auto-generated from data/maps/map_groups.json\n@\n\n";
|
|
|
|
|
2019-02-02 20:22:41 +01:00
|
|
|
for (string map_name : map_names)
|
|
|
|
text << "\t.include \"data/maps/" << map_name << "/header.inc\"\n";
|
|
|
|
|
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
string generate_events_text(Json groups_data) {
|
|
|
|
vector<string> map_names;
|
|
|
|
|
|
|
|
for (auto &group : groups_data["group_order"].array_items())
|
2023-01-17 21:25:39 +01:00
|
|
|
for (auto map_name : groups_data[json_to_string(group)].array_items())
|
|
|
|
map_names.push_back(json_to_string(map_name));
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
ostringstream text;
|
|
|
|
|
2020-07-24 09:43:37 +02:00
|
|
|
text << "@\n@ DO NOT MODIFY THIS FILE! It is auto-generated from data/maps/map_groups.json\n@\n\n";
|
|
|
|
|
2019-02-02 20:22:41 +01:00
|
|
|
for (string map_name : map_names)
|
|
|
|
text << "\t.include \"data/maps/" << map_name << "/events.inc\"\n";
|
|
|
|
|
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
string generate_map_constants_text(string groups_filepath, Json groups_data) {
|
|
|
|
string file_dir = get_directory_name(groups_filepath);
|
|
|
|
char dir_separator = file_dir.back();
|
|
|
|
|
|
|
|
ostringstream text;
|
2022-09-10 05:34:05 +02:00
|
|
|
ostringstream mapCountText;
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
text << "#ifndef GUARD_CONSTANTS_MAP_GROUPS_H\n"
|
|
|
|
<< "#define GUARD_CONSTANTS_MAP_GROUPS_H\n\n";
|
|
|
|
|
2020-07-24 09:43:37 +02:00
|
|
|
text << "//\n// DO NOT MODIFY THIS FILE! It is auto-generated from data/maps/map_groups.json\n//\n\n";
|
|
|
|
|
2019-02-02 20:22:41 +01:00
|
|
|
int group_num = 0;
|
Implementation if Pyredrid and AsparagusEduardo debug menu plus huge rewrite and tons of additions
V2: Fly, Warp, Flags, Vars, give items, give pkm 2 versions
Improved cheats, reworked the vars system
vars function now starts at VARS_START and end VARS_END
Figured out how to display FieldMessages, reimplemented CheckSafeBlock, cleanup
DebugAction_DestroyExtraWindow instead of multiple, renamed text variables
cleanup + pokemon simple
give pokemon complex nearly done
Complex pkm works, items now with icons
if statement cleanup
alter build tools to include maps per map group
Warp functionallity
added hex value to flags and vars
cleanup
Credits
2020-09-26 00:51:02 +02:00
|
|
|
vector<int> map_count_vec; //DEBUG
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
for (auto &group : groups_data["group_order"].array_items()) {
|
2023-01-17 21:40:39 +01:00
|
|
|
string groupName = json_to_string(group);
|
|
|
|
text << "// " << groupName << "\n";
|
2023-04-21 09:20:36 +02:00
|
|
|
vector<string> map_ids;
|
2022-09-02 18:53:51 +02:00
|
|
|
size_t max_length = 0;
|
2022-09-13 21:26:36 +02:00
|
|
|
|
Implementation if Pyredrid and AsparagusEduardo debug menu plus huge rewrite and tons of additions
V2: Fly, Warp, Flags, Vars, give items, give pkm 2 versions
Improved cheats, reworked the vars system
vars function now starts at VARS_START and end VARS_END
Figured out how to display FieldMessages, reimplemented CheckSafeBlock, cleanup
DebugAction_DestroyExtraWindow instead of multiple, renamed text variables
cleanup + pokemon simple
give pokemon complex nearly done
Complex pkm works, items now with icons
if statement cleanup
alter build tools to include maps per map group
Warp functionallity
added hex value to flags and vars
cleanup
Credits
2020-09-26 00:51:02 +02:00
|
|
|
int map_count = 0; //DEBUG
|
2019-02-02 20:22:41 +01:00
|
|
|
|
2023-01-17 21:40:39 +01:00
|
|
|
for (auto &map_name : groups_data[groupName].array_items()) {
|
2023-04-21 09:20:36 +02:00
|
|
|
string map_filepath = file_dir + json_to_string(map_name) + dir_separator + "map.json";
|
2019-02-02 20:22:41 +01:00
|
|
|
string err_str;
|
2023-04-21 09:20:36 +02:00
|
|
|
Json map_data = Json::parse(read_text_file(map_filepath), err_str);
|
|
|
|
if (map_data == Json())
|
|
|
|
FATAL_ERROR("%s: %s\n", map_filepath.c_str(), err_str.c_str());
|
|
|
|
string id = json_to_string(map_data, "id", true);
|
|
|
|
map_ids.push_back(id);
|
2023-01-17 21:40:39 +01:00
|
|
|
if (id.length() > max_length)
|
|
|
|
max_length = id.length();
|
Implementation if Pyredrid and AsparagusEduardo debug menu plus huge rewrite and tons of additions
V2: Fly, Warp, Flags, Vars, give items, give pkm 2 versions
Improved cheats, reworked the vars system
vars function now starts at VARS_START and end VARS_END
Figured out how to display FieldMessages, reimplemented CheckSafeBlock, cleanup
DebugAction_DestroyExtraWindow instead of multiple, renamed text variables
cleanup + pokemon simple
give pokemon complex nearly done
Complex pkm works, items now with icons
if statement cleanup
alter build tools to include maps per map group
Warp functionallity
added hex value to flags and vars
cleanup
Credits
2020-09-26 00:51:02 +02:00
|
|
|
map_count++; //DEBUG
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int map_id_num = 0;
|
2023-04-21 09:20:36 +02:00
|
|
|
for (string map_id : map_ids) {
|
|
|
|
text << "#define " << map_id << string((max_length - map_id.length() + 1), ' ')
|
2019-02-02 20:22:41 +01:00
|
|
|
<< "(" << map_id_num++ << " | (" << group_num << " << 8))\n";
|
|
|
|
}
|
|
|
|
text << "\n";
|
|
|
|
|
|
|
|
group_num++;
|
Implementation if Pyredrid and AsparagusEduardo debug menu plus huge rewrite and tons of additions
V2: Fly, Warp, Flags, Vars, give items, give pkm 2 versions
Improved cheats, reworked the vars system
vars function now starts at VARS_START and end VARS_END
Figured out how to display FieldMessages, reimplemented CheckSafeBlock, cleanup
DebugAction_DestroyExtraWindow instead of multiple, renamed text variables
cleanup + pokemon simple
give pokemon complex nearly done
Complex pkm works, items now with icons
if statement cleanup
alter build tools to include maps per map group
Warp functionallity
added hex value to flags and vars
cleanup
Credits
2020-09-26 00:51:02 +02:00
|
|
|
map_count_vec.push_back(map_count); //DEBUG
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
text << "#define MAP_GROUPS_COUNT " << group_num << "\n\n";
|
|
|
|
text << "#endif // GUARD_CONSTANTS_MAP_GROUPS_H\n";
|
|
|
|
|
2022-09-10 05:34:05 +02:00
|
|
|
char s = file_dir.back();
|
|
|
|
mapCountText << "static const u8 MAP_GROUP_COUNT[] = {"; //DEBUG
|
|
|
|
for(int i=0; i<group_num; i++){ //DEBUG
|
|
|
|
mapCountText << map_count_vec[i] << ", "; //DEBUG
|
|
|
|
} //DEBUG
|
|
|
|
mapCountText << "0};\n"; //DEBUG
|
|
|
|
write_text_file(file_dir + ".." + s + ".." + s + "src" + s + "data" + s + "map_group_count.h", mapCountText.str());
|
|
|
|
|
2019-02-02 20:22:41 +01:00
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
void process_groups(string groups_filepath) {
|
|
|
|
string err;
|
|
|
|
Json groups_data = Json::parse(read_text_file(groups_filepath), err);
|
|
|
|
|
|
|
|
if (groups_data == Json())
|
|
|
|
FATAL_ERROR("%s\n", err.c_str());
|
|
|
|
|
|
|
|
string groups_text = generate_groups_text(groups_data);
|
|
|
|
string connections_text = generate_connections_text(groups_data);
|
|
|
|
string headers_text = generate_headers_text(groups_data);
|
|
|
|
string events_text = generate_events_text(groups_data);
|
|
|
|
string map_header_text = generate_map_constants_text(groups_filepath, groups_data);
|
|
|
|
|
|
|
|
string file_dir = get_directory_name(groups_filepath);
|
|
|
|
char s = file_dir.back();
|
|
|
|
|
|
|
|
write_text_file(file_dir + "groups.inc", groups_text);
|
|
|
|
write_text_file(file_dir + "connections.inc", connections_text);
|
|
|
|
write_text_file(file_dir + "headers.inc", headers_text);
|
|
|
|
write_text_file(file_dir + "events.inc", events_text);
|
|
|
|
write_text_file(file_dir + ".." + s + ".." + s + "include" + s + "constants" + s + "map_groups.h", map_header_text);
|
|
|
|
}
|
|
|
|
|
|
|
|
string generate_layout_headers_text(Json layouts_data) {
|
|
|
|
ostringstream text;
|
|
|
|
|
2020-07-24 09:43:37 +02:00
|
|
|
text << "@\n@ DO NOT MODIFY THIS FILE! It is auto-generated from data/layouts/layouts.json\n@\n\n";
|
|
|
|
|
2019-02-02 20:22:41 +01:00
|
|
|
for (auto &layout : layouts_data["layouts"].array_items()) {
|
2023-02-08 18:10:17 +01:00
|
|
|
if (layout == Json::object()) continue;
|
2023-01-17 22:11:15 +01:00
|
|
|
string layoutName = json_to_string(layout, "name");
|
2023-01-17 21:40:39 +01:00
|
|
|
string border_label = layoutName + "_Border";
|
|
|
|
string blockdata_label = layoutName + "_Blockdata";
|
2019-02-02 20:22:41 +01:00
|
|
|
text << border_label << "::\n"
|
2023-01-17 22:11:15 +01:00
|
|
|
<< "\t.incbin \"" << json_to_string(layout, "border_filepath") << "\"\n\n"
|
2019-02-02 20:22:41 +01:00
|
|
|
<< blockdata_label << "::\n"
|
2023-01-17 22:11:15 +01:00
|
|
|
<< "\t.incbin \"" << json_to_string(layout, "blockdata_filepath") << "\"\n\n"
|
2019-02-02 20:22:41 +01:00
|
|
|
<< "\t.align 2\n"
|
2023-01-17 21:40:39 +01:00
|
|
|
<< layoutName << "::\n"
|
2023-01-17 22:11:15 +01:00
|
|
|
<< "\t.4byte " << json_to_string(layout, "width") << "\n"
|
|
|
|
<< "\t.4byte " << json_to_string(layout, "height") << "\n"
|
2019-02-02 20:22:41 +01:00
|
|
|
<< "\t.4byte " << border_label << "\n"
|
|
|
|
<< "\t.4byte " << blockdata_label << "\n"
|
2023-01-17 22:11:15 +01:00
|
|
|
<< "\t.4byte " << json_to_string(layout, "primary_tileset") << "\n"
|
2023-02-08 18:10:17 +01:00
|
|
|
<< "\t.4byte " << json_to_string(layout, "secondary_tileset") << "\n";
|
|
|
|
if (version == "firered") {
|
|
|
|
text << "\t.byte " << json_to_string(layout, "border_width") << "\n"
|
|
|
|
<< "\t.byte " << json_to_string(layout, "border_height") << "\n"
|
|
|
|
<< "\t.2byte 0\n";
|
|
|
|
}
|
|
|
|
text << "\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
string generate_layouts_table_text(Json layouts_data) {
|
|
|
|
ostringstream text;
|
|
|
|
|
2020-07-24 09:43:37 +02:00
|
|
|
text << "@\n@ DO NOT MODIFY THIS FILE! It is auto-generated from data/layouts/layouts.json\n@\n\n";
|
|
|
|
|
2019-02-02 20:22:41 +01:00
|
|
|
text << "\t.align 2\n"
|
2023-01-17 22:11:15 +01:00
|
|
|
<< json_to_string(layouts_data, "layouts_table_label") << "::\n";
|
2019-02-02 20:22:41 +01:00
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
for (auto &layout : layouts_data["layouts"].array_items()) {
|
|
|
|
string layout_name = json_to_string(layout, "name", true);
|
|
|
|
if (layout_name.empty()) layout_name = "NULL";
|
|
|
|
text << "\t.4byte " << layout_name << "\n";
|
|
|
|
}
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
string generate_layouts_constants_text(Json layouts_data) {
|
|
|
|
ostringstream text;
|
|
|
|
|
|
|
|
text << "#ifndef GUARD_CONSTANTS_LAYOUTS_H\n"
|
|
|
|
<< "#define GUARD_CONSTANTS_LAYOUTS_H\n\n";
|
|
|
|
|
2020-07-24 09:43:37 +02:00
|
|
|
text << "//\n// DO NOT MODIFY THIS FILE! It is auto-generated from data/layouts/layouts.json\n//\n\n";
|
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
int i = 1;
|
|
|
|
for (auto &layout : layouts_data["layouts"].array_items()) {
|
|
|
|
if (layout != Json::object())
|
|
|
|
text << "#define " << json_to_string(layout, "id") << " " << i << "\n";
|
|
|
|
i++;
|
|
|
|
}
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
text << "\n#endif // GUARD_CONSTANTS_LAYOUTS_H\n";
|
|
|
|
|
|
|
|
return text.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
void process_layouts(string layouts_filepath) {
|
|
|
|
string err;
|
|
|
|
Json layouts_data = Json::parse(read_text_file(layouts_filepath), err);
|
|
|
|
|
|
|
|
if (layouts_data == Json())
|
|
|
|
FATAL_ERROR("%s\n", err.c_str());
|
|
|
|
|
|
|
|
string layout_headers_text = generate_layout_headers_text(layouts_data);
|
|
|
|
string layouts_table_text = generate_layouts_table_text(layouts_data);
|
|
|
|
string layouts_constants_text = generate_layouts_constants_text(layouts_data);
|
|
|
|
|
|
|
|
string file_dir = get_directory_name(layouts_filepath);
|
|
|
|
char s = file_dir.back();
|
|
|
|
|
|
|
|
write_text_file(file_dir + "layouts.inc", layout_headers_text);
|
|
|
|
write_text_file(file_dir + "layouts_table.inc", layouts_table_text);
|
|
|
|
write_text_file(file_dir + ".." + s + ".." + s + "include" + s + "constants" + s + "layouts.h", layouts_constants_text);
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
2019-02-05 00:28:45 +01:00
|
|
|
if (argc < 3)
|
|
|
|
FATAL_ERROR("USAGE: mapjson <mode> <game-version> [options]\n");
|
|
|
|
|
|
|
|
char *version_arg = argv[2];
|
2023-02-08 18:10:17 +01:00
|
|
|
version = string(version_arg);
|
|
|
|
if (version != "emerald" && version != "ruby" && version != "firered")
|
|
|
|
FATAL_ERROR("ERROR: <game-version> must be 'emerald', 'firered', or 'ruby'.\n");
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
char *mode_arg = argv[1];
|
|
|
|
string mode(mode_arg);
|
|
|
|
if (mode != "layouts" && mode != "map" && mode != "groups")
|
|
|
|
FATAL_ERROR("ERROR: <mode> must be 'layouts', 'map', or 'groups'.\n");
|
|
|
|
|
|
|
|
if (mode == "map") {
|
2019-02-05 00:28:45 +01:00
|
|
|
if (argc != 5)
|
|
|
|
FATAL_ERROR("USAGE: mapjson map <game-version> <map_file> <layouts_file>\n");
|
2019-02-02 20:22:41 +01:00
|
|
|
|
2019-02-05 00:28:45 +01:00
|
|
|
string filepath(argv[3]);
|
|
|
|
string layouts_filepath(argv[4]);
|
2019-02-02 20:22:41 +01:00
|
|
|
|
2023-02-08 18:10:17 +01:00
|
|
|
process_map(filepath, layouts_filepath);
|
2019-02-02 20:22:41 +01:00
|
|
|
}
|
|
|
|
else if (mode == "groups") {
|
2019-02-05 00:28:45 +01:00
|
|
|
if (argc != 4)
|
|
|
|
FATAL_ERROR("USAGE: mapjson groups <game-version> <groups_file>\n");
|
2019-02-02 20:22:41 +01:00
|
|
|
|
2019-02-05 00:28:45 +01:00
|
|
|
string filepath(argv[3]);
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
process_groups(filepath);
|
|
|
|
}
|
|
|
|
else if (mode == "layouts") {
|
2019-02-05 00:28:45 +01:00
|
|
|
if (argc != 4)
|
|
|
|
FATAL_ERROR("USAGE: mapjson layouts <game-version> <layouts_file>\n");
|
2019-02-02 20:22:41 +01:00
|
|
|
|
2019-02-05 00:28:45 +01:00
|
|
|
string filepath(argv[3]);
|
2019-02-02 20:22:41 +01:00
|
|
|
|
|
|
|
process_layouts(filepath);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|