sots-engine/tests/game_design/stock_designs.cpp

95 lines
3.6 KiB
C++

#include "stock_designs.h"
#include <fstream>
#include <sstream>
#include "game/data/common.h"
#include "json_min.h"
using namespace game::design;
using json_min::Value;
namespace {
std::vector<std::string> strings(const Value& v) {
std::vector<std::string> out;
for (const Value& x : v.items)
if (x.is_string()) out.push_back(x.str());
return out;
}
} // namespace
bool load_stock_designs(const std::string& path, std::vector<StockDesign>& out, std::string& err) {
std::ifstream in(path, std::ios::binary);
if (!in) {
err = "cannot read " + path;
return false;
}
std::ostringstream ss;
ss << in.rdbuf();
Value root;
if (!json_min::parse(ss.str(), root, err)) return false;
if (!root.is_array()) {
err = "expected a list of players";
return false;
}
int pi = 0;
for (const Value& player : root.items) {
int di = 0;
for (const Value& d : player["designs"].items) {
StockDesign sd;
sd.player_index = pi;
sd.design_index = di++;
sd.save = player["save"].str();
sd.player = player["player"].str();
sd.npc = player["npc"].as_bool();
sd.race_text = d["race"].str();
sd.list = d["list"].str();
Design& des = sd.design;
des.name = d["name"].str();
des.hidden = d["hidden"].as_bool();
des.designer_made = d["faiDes"].as_bool();
des.default_weapons = d["dWep"].as_int();
des.race = game::data::parse_species(sd.race_text);
if (!d["known_techs"].is_null()) des.known_techs = strings(d["known_techs"]);
const Value& raw = d["raw_slots"];
if (!raw.is_array() || raw.items.size() != static_cast<std::size_t>(kSlotCount)) {
err = des.name + ": raw_slots must have " + std::to_string(kSlotCount) + " entries";
return false;
}
for (int i = 0; i < kSlotCount; ++i) {
const Value& r = raw.items[static_cast<std::size_t>(i)];
SectionUse& u = des.slots[static_cast<std::size_t>(i)];
int species = r["species"].as_int();
u.section_id = r["section_id"].as_int();
if (species == 0 && u.section_id == 0) continue; // empty slot
u.species = static_cast<game::data::Species>(species);
const Value& weapons = r["weapons"];
const Value& riders = r["rider_design_ids"];
for (std::size_t w = 0; w < weapons.items.size(); ++w) {
const Value& x = weapons.items[w];
WeaponRef ref;
if (x.is_number()) ref = WeaponRef::by_id(x.as_int());
else if (x.is_string()) ref = WeaponRef::by_file(x.str());
if (w < riders.items.size()) ref.rider_design_id = riders.items[w].as_int();
u.weapons.push_back(ref);
}
u.options = strings(r["options"]);
if (i < 3) {
sd.dopts[static_cast<std::size_t>(i)] = u.options;
sd.bank_count[static_cast<std::size_t>(i)] = r["bank_count"].as_int();
}
}
for (std::size_t i = 0; i < 3; ++i) {
const Value& view = d[slot_name(kUsedSlots[i])];
if (view.is_null()) continue;
sd.expect_stem[i] = view["section"].str();
sd.expect_options[i] = strings(view["options"]);
}
out.push_back(std::move(sd));
}
++pi;
}
return true;
}