use new JSON helpers

This commit is contained in:
Martin Michelsen
2023-08-30 18:44:21 -07:00
parent be4837cccf
commit 2304a17dd0
7 changed files with 110 additions and 116 deletions
+28 -30
View File
@@ -1089,39 +1089,37 @@ Rules::Rules() {
Rules::Rules(const JSON& json) {
this->clear();
auto dict = json.as_dict();
this->overall_time_limit = json.get("overall_time_limit", this->overall_time_limit);
this->phase_time_limit = json.get("phase_time_limit", this->phase_time_limit);
this->overall_time_limit = json.get_int("overall_time_limit", this->overall_time_limit);
this->phase_time_limit = json.get_int("phase_time_limit", this->phase_time_limit);
this->allowed_cards = json.get_enum("allowed_cards", this->allowed_cards);
this->min_dice = json.get("min_dice", this->min_dice);
this->max_dice = json.get("max_dice", this->max_dice);
this->disable_deck_shuffle = json.get("disable_deck_shuffle", this->disable_deck_shuffle);
this->disable_deck_loop = json.get("disable_deck_loop", this->disable_deck_loop);
this->char_hp = json.get("char_hp", this->char_hp);
this->min_dice = json.get_int("min_dice", this->min_dice);
this->max_dice = json.get_int("max_dice", this->max_dice);
this->disable_deck_shuffle = json.get_bool("disable_deck_shuffle", this->disable_deck_shuffle);
this->disable_deck_loop = json.get_bool("disable_deck_loop", this->disable_deck_loop);
this->char_hp = json.get_int("char_hp", this->char_hp);
this->hp_type = json.get_enum("hp_type", this->hp_type);
this->no_assist_cards = json.get("no_assist_cards", this->no_assist_cards);
this->disable_dialogue = json.get("disable_dialogue", this->disable_dialogue);
this->no_assist_cards = json.get_bool("no_assist_cards", this->no_assist_cards);
this->disable_dialogue = json.get_bool("disable_dialogue", this->disable_dialogue);
this->dice_exchange_mode = json.get_enum("dice_exchange_mode", this->dice_exchange_mode);
this->disable_dice_boost = json.get("disable_dice_boost", this->disable_dice_boost);
this->disable_dice_boost = json.get_bool("disable_dice_boost", this->disable_dice_boost);
}
JSON Rules::json() const {
unordered_map<string, JSON> dict;
dict.emplace("overall_time_limit", this->overall_time_limit);
dict.emplace("phase_time_limit", this->phase_time_limit);
dict.emplace("allowed_cards", name_for_enum(this->allowed_cards));
dict.emplace("min_dice", this->min_dice);
dict.emplace("max_dice", this->max_dice);
dict.emplace("disable_deck_shuffle", this->disable_deck_shuffle);
dict.emplace("disable_deck_loop", this->disable_deck_loop);
dict.emplace("char_hp", this->char_hp);
dict.emplace("hp_type", name_for_enum(this->hp_type));
dict.emplace("no_assist_cards", this->no_assist_cards);
dict.emplace("disable_dialogue", this->disable_dialogue);
dict.emplace("dice_exchange_mode", name_for_enum(this->dice_exchange_mode));
dict.emplace("disable_dice_boost", this->disable_dice_boost);
return JSON(std::move(dict));
return JSON::dict({
{"overall_time_limit", this->overall_time_limit},
{"phase_time_limit", this->phase_time_limit},
{"allowed_cards", name_for_enum(this->allowed_cards)},
{"min_dice", this->min_dice},
{"max_dice", this->max_dice},
{"disable_deck_shuffle", this->disable_deck_shuffle},
{"disable_deck_loop", this->disable_deck_loop},
{"char_hp", this->char_hp},
{"hp_type", name_for_enum(this->hp_type)},
{"no_assist_cards", this->no_assist_cards},
{"disable_dialogue", this->disable_dialogue},
{"dice_exchange_mode", name_for_enum(this->dice_exchange_mode)},
{"disable_dice_boost", this->disable_dice_boost},
});
}
void Rules::set_defaults() {
@@ -2004,9 +2002,9 @@ COMDeckIndex::COMDeckIndex(const string& filename) {
for (const auto& def_json : json.as_list()) {
auto& def = this->decks.emplace_back(new COMDeckDefinition());
def->index = this->decks.size() - 1;
def->player_name = def_json.at(0).as_string();
def->deck_name = def_json.at(1).as_string();
auto card_ids_json = def_json.at(2);
def->player_name = def_json->at(0).as_string();
def->deck_name = def_json->at(1).as_string();
auto card_ids_json = def_json->at(2);
for (size_t z = 0; z < 0x1F; z++) {
def->card_ids[z] = card_ids_json.at(z).as_int();
}
+15 -15
View File
@@ -325,27 +325,27 @@ void Tournament::init() {
vector<size_t> team_index_to_rounds_cleared;
bool is_registration_complete;
if (this->source_json) {
this->name = this->source_json.at("name").as_string();
this->map = this->map_index->definition_for_number(this->source_json.at("map_number"));
if (!this->source_json.is_null()) {
this->name = this->source_json.get_string("name");
this->map = this->map_index->definition_for_number(this->source_json.get_int("map_number"));
this->rules = Rules(this->source_json.at("rules"));
this->is_2v2 = this->source_json.at("is_2v2");
is_registration_complete = this->source_json.at("is_registration_complete");
this->is_2v2 = this->source_json.get_bool("is_2v2");
is_registration_complete = this->source_json.get_bool("is_registration_complete");
for (const auto& team_json : this->source_json.at("teams").as_list()) {
for (const auto& team_json : this->source_json.get_list("teams")) {
auto& team = this->teams.emplace_back(new Team(
this->shared_from_this(),
this->teams.size(),
team_json.at("max_players")));
team->name = team_json.at("name").as_string();
team->password = team_json.at("password").as_string();
team_index_to_rounds_cleared.emplace_back(team_json.at("num_rounds_cleared"));
for (const auto& player_json : team_json.at("player_specs").as_list()) {
if (player_json.is_int()) {
team->players.emplace_back(player_json);
this->all_player_serial_numbers.emplace(player_json);
team_json->get_int("max_players")));
team->name = team_json->get_string("name");
team->password = team_json->get_string("password");
team_index_to_rounds_cleared.emplace_back(team_json->get_int("num_rounds_cleared"));
for (const auto& player_json : team_json->get_list("player_specs")) {
if (player_json->is_int()) {
team->players.emplace_back(player_json->as_int());
this->all_player_serial_numbers.emplace(player_json->as_int());
} else {
team->players.emplace_back(this->com_deck_index->deck_for_name(player_json));
team->players.emplace_back(this->com_deck_index->deck_for_name(player_json->as_string()));
}
}
}
+9 -12
View File
@@ -43,7 +43,7 @@ template <typename T>
vector<T> parse_int_vector(const JSON& o) {
vector<T> ret;
for (const auto& x : o.as_list()) {
ret.emplace_back(x.as_int());
ret.emplace_back(x->as_int());
}
return ret;
}
@@ -1400,7 +1400,7 @@ int main(int argc, char** argv) {
return ret;
};
JSON::dict_type episodes_dict;
auto episodes_dict = JSON::dict();
static const array<pair<Episode, vector<vector<EnemyType>>>, 3> episodes = {
make_pair(Episode::EP1, generate_table(Episode::EP1)),
make_pair(Episode::EP2, generate_table(Episode::EP2)),
@@ -1409,11 +1409,11 @@ int main(int argc, char** argv) {
for (const auto& episode_it : episodes) {
Episode episode = episode_it.first;
const auto& rt_index_to_enemy_type = episode_it.second;
JSON::dict_type difficulty_dict;
auto difficulty_dict = JSON::dict();
for (uint8_t difficulty = 0; difficulty < 4; difficulty++) {
JSON::dict_type section_id_dict;
auto section_id_dict = JSON::dict();
for (uint8_t section_id = 0; section_id < 10; section_id++) {
JSON::dict_type collection_dict;
auto collection_dict = JSON::dict();
for (size_t rt_index = 0; rt_index < rt_index_to_enemy_type.size(); rt_index++) {
const auto& enemy_types = rt_index_to_enemy_type[rt_index];
@@ -1428,18 +1428,17 @@ int main(int argc, char** argv) {
}
auto frac = reduce_fraction<uint64_t>(spec.probability, 0x100000000);
JSON::list_type specs_list;
JSON specs_json = {JSON::list({string_printf("%" PRIu64 "/%" PRIu64, frac.first, frac.second), primary_identifier})};
auto specs_json = JSON::list({JSON::list({string_printf("%" PRIu64 "/%" PRIu64, frac.first, frac.second), primary_identifier})});
for (const auto& enemy_type : enemy_types) {
if (enemy_type_valid_for_episode(episode, enemy_type)) {
collection_dict.emplace(name_for_enum(enemy_type), specs_json);
collection_dict.emplace(name_for_enum(enemy_type), std::move(specs_json));
}
}
}
}
for (size_t area = 0; area < 0x12; area++) {
JSON::list_type area_list;
auto area_list = JSON::list();
for (const auto& spec : rs.get_box_specs(GameMode::NORMAL, episode, difficulty, section_id, area)) {
uint32_t primary_identifier = (spec.item_code[0] << 16) | (spec.item_code[1] << 8) | spec.item_code[2];
@@ -1466,9 +1465,7 @@ int main(int argc, char** argv) {
episodes_dict.emplace(token_name_for_episode(episode), std::move(difficulty_dict));
}
JSON::dict_type root_dict;
root_dict.emplace("Normal", std::move(episodes_dict));
JSON root_json = std::move(root_dict);
auto root_json = JSON::dict({{"Normal", std::move(episodes_dict)}});
string json_data = root_json.serialize(
JSON::SerializeOption::FORMAT |
JSON::SerializeOption::HEX_INTEGERS |
+8 -9
View File
@@ -78,9 +78,8 @@ PatchFileIndex::PatchFileIndex(const string& root_dir)
JSON cache_item_json;
try {
cache_item_json = metadata_cache_json.at(relative_item_path);
auto cache_item = metadata_cache_json.at(relative_item_path).as_list();
uint64_t cached_size = cache_item.at(0);
uint64_t cached_mtime = cache_item.at(1);
uint64_t cached_size = cache_item_json.get_int(0);
uint64_t cached_mtime = cache_item_json.get_int(1);
if (static_cast<uint64_t>(st.st_mtime) != cached_mtime) {
throw runtime_error("file has been modified");
}
@@ -88,9 +87,9 @@ PatchFileIndex::PatchFileIndex(const string& root_dir)
throw runtime_error("file size has changed");
}
f->size = cached_size;
f->crc32 = cache_item.at(2);
for (const auto& chunk_crc32_json : cache_item.at(3).as_list()) {
f->chunk_crcs.emplace_back(chunk_crc32_json.as_int());
f->crc32 = cache_item_json.get_int(2);
for (const auto& chunk_crc32_json : cache_item_json.get_list(3)) {
f->chunk_crcs.emplace_back(chunk_crc32_json->as_int());
}
} catch (const exception& e) {
@@ -106,18 +105,18 @@ PatchFileIndex::PatchFileIndex(const string& root_dir)
}
// File was modified or cache item was missing; make a new cache item
vector<JSON> chunk_crcs_item;
auto chunk_crcs_item = JSON::list();
for (uint32_t chunk_crc : f->chunk_crcs) {
chunk_crcs_item.emplace_back(chunk_crc);
}
new_metadata_cache_json.as_dict().emplace(
new_metadata_cache_json.emplace(
relative_item_path, JSON::list({f->size, st.st_mtime, f->crc32, std::move(chunk_crcs_item)}));
should_write_metadata_cache = true;
} else {
// File was not modified and cache item was valid; just use the
// existing cache item
new_metadata_cache_json.as_dict().emplace(
new_metadata_cache_json.emplace(
relative_item_path, std::move(cache_item_json));
}
+6 -6
View File
@@ -23,11 +23,11 @@ using namespace std;
QuestCategoryIndex::Category::Category(uint32_t category_id, const JSON& json)
: category_id(category_id) {
this->flags = json.at(0);
this->type = json.at(1).as_string().at(0);
this->short_token = json.at(2).as_string();
this->name = decode_sjis(json.at(3));
this->description = decode_sjis(json.at(4));
this->flags = json.get_int(0);
this->type = json.get_string(1).at(0);
this->short_token = json.get_string(2);
this->name = decode_sjis(json.get_string(3));
this->description = decode_sjis(json.get_string(4));
}
bool QuestCategoryIndex::Category::matches_flags(uint8_t request) const {
@@ -42,7 +42,7 @@ bool QuestCategoryIndex::Category::matches_flags(uint8_t request) const {
QuestCategoryIndex::QuestCategoryIndex(const JSON& json) {
uint32_t next_category_id = 1;
for (const auto& it : json.as_list()) {
this->categories.emplace_back(next_category_id++, it);
this->categories.emplace_back(next_category_id++, *it);
}
}
+10 -11
View File
@@ -176,21 +176,21 @@ JSONRareItemSet::JSONRareItemSet(const JSON& json) {
{{"Normal", GameMode::NORMAL}, {"Battle", GameMode::BATTLE}, {"Challenge", GameMode::CHALLENGE}, {"Solo", GameMode::SOLO}});
GameMode mode = mode_keys.at(mode_it.first);
for (const auto& episode_it : mode_it.second.as_dict()) {
for (const auto& episode_it : mode_it.second->as_dict()) {
static const unordered_map<string, Episode> episode_keys(
{{"Episode1", Episode::EP1}, {"Episode2", Episode::EP2}, {"Episode4", Episode::EP4}});
Episode episode = episode_keys.at(episode_it.first);
for (const auto& difficulty_it : episode_it.second.as_dict()) {
for (const auto& difficulty_it : episode_it.second->as_dict()) {
static const unordered_map<string, uint8_t> difficulty_keys(
{{"Normal", 0}, {"Hard", 1}, {"VeryHard", 2}, {"Ultimate", 3}});
uint8_t difficulty = difficulty_keys.at(difficulty_it.first);
for (const auto& section_id_it : difficulty_it.second.as_dict()) {
for (const auto& section_id_it : difficulty_it.second->as_dict()) {
uint8_t section_id = section_id_for_name(section_id_it.first);
auto& collection = this->collections[this->key_for_params(mode, episode, difficulty, section_id)];
for (const auto& item_it : section_id_it.second.as_dict()) {
for (const auto& item_it : section_id_it.second->as_dict()) {
vector<ExpandedDrop>* target;
if (starts_with(item_it.first, "Box-")) {
uint8_t area = area_for_name(item_it.first.substr(4));
@@ -206,15 +206,14 @@ JSONRareItemSet::JSONRareItemSet(const JSON& json) {
target = &collection.rt_index_to_specs[index];
}
for (const auto& spec_json : item_it.second.as_list()) {
auto& spec_list = spec_json.as_list();
for (const auto& spec_json : item_it.second->as_list()) {
auto& d = target->emplace_back();
auto prob_desc = spec_list.at(0);
auto prob_desc = spec_json->at(0);
if (prob_desc.is_int()) {
d.probability = prob_desc;
d.probability = prob_desc.as_int();
} else if (prob_desc.is_string()) {
auto tokens = split(prob_desc, '/');
auto tokens = split(prob_desc.as_string(), '/');
if (tokens.size() != 2) {
throw runtime_error("invalid probability specification");
}
@@ -227,9 +226,9 @@ JSONRareItemSet::JSONRareItemSet(const JSON& json) {
}
}
auto item_desc = spec_list.at(1);
auto item_desc = spec_json->at(1);
if (item_desc.is_int()) {
uint32_t item_code = item_desc;
uint32_t item_code = item_desc.as_int();
d.item_code[0] = (item_code >> 16) & 0xFF;
d.item_code[1] = (item_code >> 8) & 0xFF;
d.item_code[2] = item_code & 0xFF;
+34 -33
View File
@@ -398,11 +398,11 @@ void ServerState::create_menus(const JSON& json) {
{
uint32_t item_id = 0;
for (const auto& item : json.at("InformationMenuContents").as_list()) {
u16string name = decode_sjis(item.at(0));
u16string short_desc = decode_sjis(item.at(1));
u16string name = decode_sjis(item->get_string(0));
u16string short_desc = decode_sjis(item->get_string(1));
information_menu_v2->items.emplace_back(item_id, name, short_desc, 0);
information_menu_v3->items.emplace_back(item_id, name, short_desc, MenuItem::Flag::REQUIRES_MESSAGE_BOXES);
information_contents->emplace_back(decode_sjis(item.at(2)));
information_contents->emplace_back(decode_sjis(item->get_string(2)));
item_id++;
}
}
@@ -417,7 +417,7 @@ void ServerState::create_menus(const JSON& json) {
try {
map<string, const JSON&> sorted_jsons;
for (const auto& it : json.at(key).as_dict()) {
sorted_jsons.emplace(it.first, it.second);
sorted_jsons.emplace(it.first, *it.second);
}
ret->items.emplace_back(ProxyDestinationsMenuItemID::GO_BACK, u"Go back",
@@ -427,7 +427,7 @@ void ServerState::create_menus(const JSON& json) {
uint32_t item_id = 0;
for (const auto& item : sorted_jsons) {
const string& netloc_str = item.second;
const string& netloc_str = item.second.as_string();
const string& description = "$C7Remote server:\n$C6" + netloc_str;
ret->items.emplace_back(item_id, decode_sjis(item.first), decode_sjis(description), 0);
ret_pds.emplace_back(parse_netloc(netloc_str));
@@ -448,7 +448,7 @@ void ServerState::create_menus(const JSON& json) {
this->proxy_destinations_xb, "ProxyDestinations-XB");
try {
const string& netloc_str = json.at("ProxyDestination-Patch");
const string& netloc_str = json.get_string("ProxyDestination-Patch");
this->proxy_destination_patch = parse_netloc(netloc_str);
config_log.info("Patch server proxy is enabled with destination %s", netloc_str.c_str());
for (auto& it : this->name_to_port_config) {
@@ -461,7 +461,7 @@ void ServerState::create_menus(const JSON& json) {
this->proxy_destination_patch.second = 0;
}
try {
const string& netloc_str = json.at("ProxyDestination-BB");
const string& netloc_str = json.get_string("ProxyDestination-BB");
this->proxy_destination_bb = parse_netloc(netloc_str);
config_log.info("BB proxy is enabled with destination %s", netloc_str.c_str());
for (auto& it : this->name_to_port_config) {
@@ -474,9 +474,9 @@ void ServerState::create_menus(const JSON& json) {
this->proxy_destination_bb.second = 0;
}
this->welcome_message = decode_sjis(json.get("WelcomeMessage", ""));
this->pc_patch_server_message = decode_sjis(json.get("PCPatchServerMessage", ""));
this->bb_patch_server_message = decode_sjis(json.get("BBPatchServerMessage", ""));
this->welcome_message = decode_sjis(json.get_string("WelcomeMessage", ""));
this->pc_patch_server_message = decode_sjis(json.get_string("PCPatchServerMessage", ""));
this->bb_patch_server_message = decode_sjis(json.get_string("BBPatchServerMessage", ""));
}
shared_ptr<const string> ServerState::load_bb_file(
@@ -554,12 +554,12 @@ JSON ServerState::load_config() const {
static vector<PortConfiguration> parse_port_configuration(const JSON& json) {
vector<PortConfiguration> ret;
for (const auto& item_json_it : json.as_dict()) {
auto item_list = item_json_it.second.as_list();
const auto& item_list = item_json_it.second;
PortConfiguration& pc = ret.emplace_back();
pc.name = item_json_it.first;
pc.port = item_list[0];
pc.version = version_for_name(item_list[1].as_string().c_str());
pc.behavior = server_behavior_for_name(item_list[2].as_string().c_str());
pc.port = item_list->at(0).as_int();
pc.version = version_for_name(item_list->at(1).as_string().c_str());
pc.behavior = server_behavior_for_name(item_list->at(2).as_string().c_str());
}
return ret;
}
@@ -607,33 +607,34 @@ void ServerState::parse_config(const JSON& json) {
}
this->all_addresses.emplace("<external>", this->external_address);
this->dns_server_port = json.get("DNSServerPort", this->dns_server_port);
this->dns_server_port = json.get_int("DNSServerPort", this->dns_server_port);
try {
for (const auto& item : json.at("IPStackListen").as_list()) {
this->ip_stack_addresses.emplace_back(item.as_string());
this->ip_stack_addresses.emplace_back(item->as_string());
}
} catch (const out_of_range&) {
}
this->ip_stack_debug = json.get("IPStackDebug", this->ip_stack_debug);
this->allow_unregistered_users = json.get("AllowUnregisteredUsers", this->allow_unregistered_users);
this->item_tracking_enabled = json.get("EnableItemTracking", this->item_tracking_enabled);
this->drops_enabled = json.get("EnableDrops", this->drops_enabled);
this->episode_3_send_function_call_enabled = json.get("EnableEpisode3SendFunctionCall", this->episode_3_send_function_call_enabled);
this->catch_handler_exceptions = json.get("CatchHandlerExceptions", this->catch_handler_exceptions);
this->proxy_allow_save_files = json.get("ProxyAllowSaveFiles", this->proxy_allow_save_files);
this->proxy_enable_login_options = json.get("ProxyEnableLoginOptions", this->proxy_enable_login_options);
this->ep3_behavior_flags = json.get("Episode3BehaviorFlags", this->ep3_behavior_flags);
this->ep3_card_auction_points = json.get("CardAuctionPoints", this->ep3_card_auction_points);
this->ip_stack_debug = json.get_bool("IPStackDebug", this->ip_stack_debug);
this->allow_unregistered_users = json.get_bool("AllowUnregisteredUsers", this->allow_unregistered_users);
this->item_tracking_enabled = json.get_bool("EnableItemTracking", this->item_tracking_enabled);
this->drops_enabled = json.get_bool("EnableDrops", this->drops_enabled);
this->episode_3_send_function_call_enabled = json.get_bool("EnableEpisode3SendFunctionCall", this->episode_3_send_function_call_enabled);
this->catch_handler_exceptions = json.get_bool("CatchHandlerExceptions", this->catch_handler_exceptions);
this->ep3_infinite_meseta = json.get_bool("Episode3InfiniteMeseta", this->ep3_infinite_meseta);
this->proxy_allow_save_files = json.get_bool("ProxyAllowSaveFiles", this->proxy_allow_save_files);
this->proxy_enable_login_options = json.get_bool("ProxyEnableLoginOptions", this->proxy_enable_login_options);
this->ep3_behavior_flags = json.get_int("Episode3BehaviorFlags", this->ep3_behavior_flags);
this->ep3_card_auction_points = json.get_int("CardAuctionPoints", this->ep3_card_auction_points);
try {
const auto& i = json.at("CardAuctionSize");
if (i.is_int()) {
this->ep3_card_auction_min_size = i;
this->ep3_card_auction_min_size = i.as_int();
this->ep3_card_auction_max_size = this->ep3_card_auction_min_size;
} else {
this->ep3_card_auction_min_size = i.at(0);
this->ep3_card_auction_max_size = i.at(1);
this->ep3_card_auction_min_size = i.at(0).as_int();
this->ep3_card_auction_max_size = i.at(1).as_int();
}
} catch (const out_of_range&) {
this->ep3_card_auction_min_size = 0;
@@ -643,13 +644,13 @@ void ServerState::parse_config(const JSON& json) {
for (const auto& it : json.at("CardAuctionPool").as_dict()) {
this->ep3_card_auction_pool.emplace_back(
CardAuctionPoolEntry{
.probability = it.second.at(0),
.probability = static_cast<uint64_t>(it.second->at(0).as_int()),
.card_id = 0,
.min_price = it.second.at(1),
.min_price = static_cast<uint16_t>(it.second->at(1).as_int()),
.card_name = it.first});
}
set_log_levels_from_json(json.get("LogLevels", JSON::dict_type()));
set_log_levels_from_json(json.get("LogLevels", JSON::dict()));
for (const string& filename : list_directory("system/blueburst/keys")) {
if (!ends_with(filename, ".nsk")) {
@@ -692,7 +693,7 @@ void ServerState::parse_config(const JSON& json) {
} catch (const out_of_range&) {
}
this->ep3_menu_song = json.get("Episode3MenuSong", this->ep3_menu_song);
this->ep3_menu_song = json.get_int("Episode3MenuSong", this->ep3_menu_song);
try {
this->quest_category_index.reset(new QuestCategoryIndex(json.at("QuestCategories")));