Files
dota_factory/src/lib/config/ConfigLoaderShips.cpp

134 lines
5.4 KiB
C++

#include "ConfigLoader.h"
#include <cstdint>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include <QPoint>
#include "toml.hpp"
#include "Rotation.h"
#include "ShipLayout.h"
#include "TomlHelpers.h"
namespace
{
Rotation parseRotationString(const std::string& s)
{
if (s == "east") { return Rotation::East; }
if (s == "south") { return Rotation::South; }
if (s == "west") { return Rotation::West; }
return Rotation::North;
}
std::vector<PlacedModule> parsePlacedModules(const toml::array& arr,
const std::string& file,
const std::string& path)
{
std::vector<PlacedModule> result;
result.reserve(arr.size());
for (std::size_t i = 0; i < arr.size(); ++i)
{
const std::string elemPath = path + "[" + std::to_string(i) + "]";
const toml::table* t = arr[i].as_table();
if (t == nullptr) { continue; }
toml::table& mt = const_cast<toml::table&>(*t);
const std::optional<std::string> type = mt["type"].value<std::string>();
const std::optional<int64_t> x = mt["x"].value<int64_t>();
const std::optional<int64_t> y = mt["y"].value<int64_t>();
const std::optional<std::string> rot = mt["rotation"].value<std::string>();
if (!type || !x || !y || !rot) { continue; }
PlacedModule pm;
pm.moduleId = *type;
pm.position = QPoint(static_cast<int>(*x), static_cast<int>(*y));
pm.rotation = parseRotationString(*rot);
result.push_back(std::move(pm));
}
return result;
}
} // namespace
ShipsConfig ConfigLoader::loadShips(const std::string& path)
{
const std::string file = "ships.toml";
toml::table tbl = utility::parseFile(path, file);
ShipsConfig cfg;
const toml::array& arr = utility::requireArray(tbl["ship"], file, "ship");
for (std::size_t i = 0; i < arr.size(); ++i)
{
const std::string elemPath = "ship[" + std::to_string(i) + "]";
const toml::table* st = arr[i].as_table();
if (st == nullptr)
{
throw utility::makeError(file, elemPath, "not a table");
}
toml::table& mt = const_cast<toml::table&>(*st);
ShipDef def;
def.id = utility::requireString(mt["id"], file, elemPath + ".id");
def.layout = utility::requireStringArray(mt["layout"], file, elemPath + ".layout");
// Schematic
{
const std::string bpPath = elemPath + ".schematic";
const toml::table& bpTable = utility::requireTable(mt["schematic"], file, bpPath);
toml::table& bpMt = const_cast<toml::table&>(bpTable);
const toml::array& materials = utility::requireArray(bpMt["materials"], file, bpPath + ".materials");
def.schematic.materials = utility::parseIngredients(materials, file, bpPath + ".materials");
def.schematic.productionTimeSeconds = utility::requireDouble(
bpMt["production_time_seconds"], file, bpPath + ".production_time_seconds");
}
// Health
{
const std::string hPath = elemPath + ".health";
const toml::table& hTable = utility::requireTable(mt["health"], file, hPath);
toml::table& hMt = const_cast<toml::table&>(hTable);
def.health.hp = static_cast<float>(utility::requireDouble(hMt["hp"], file, hPath + ".hp"));
}
// Movement
{
const std::string mPath = elemPath + ".movement";
const toml::table& mTable = utility::requireTable(mt["movement"], file, mPath);
toml::table& mMt = const_cast<toml::table&>(mTable);
def.movement.speed_mps = static_cast<float>(utility::requireDouble(mMt["speed_mps"], file, mPath + ".speed_mps"));
def.movement.mainAcceleration_mpss = static_cast<float>(utility::requireDouble(mMt["main_acceleration_mpss"], file, mPath + ".main_acceleration_mpss"));
def.movement.maneuveringAcceleration_mpss = static_cast<float>(utility::requireDouble(mMt["maneuvering_acceleration_mpss"], file, mPath + ".maneuvering_acceleration_mpss"));
def.movement.angularAcceleration_radpss = static_cast<float>(utility::requireDouble(mMt["angular_acceleration_radpss"], file, mPath + ".angular_acceleration_radpss"));
def.movement.maxRotationSpeed_radps = static_cast<float>(utility::requireDouble(mMt["max_rotation_speed_radps"], file, mPath + ".max_rotation_speed_radps"));
}
// Sensor
{
const std::string snsPath = elemPath + ".sensor";
const toml::table& snsTable = utility::requireTable(mt["sensor"], file, snsPath);
toml::table& snsMt = const_cast<toml::table&>(snsTable);
def.sensor.sensorRange_m = static_cast<float>(utility::requireDouble(snsMt["sensor_range_m"], file, snsPath + ".sensor_range_m"));
}
// Optional: default_modules (REQ-WAV-DEFAULT-MODULES)
if (mt.contains("default_modules"))
{
const toml::array& modArr = utility::requireArray(mt["default_modules"], file,
elemPath + ".default_modules");
def.defaultModules = parsePlacedModules(modArr, file,
elemPath + ".default_modules");
}
cfg.ships.push_back(std::move(def));
}
return cfg;
}