migrate from dynamic::Value to dv::value & total erase namespace 'dynamic'

This commit is contained in:
MihailRis 2024-09-18 23:31:18 +03:00
parent d3ba4b2e3e
commit 34d2e6d400
69 changed files with 1247 additions and 2248 deletions

View File

@ -8,7 +8,6 @@
#include "constants.hpp" #include "constants.hpp"
#include "content/Content.hpp" #include "content/Content.hpp"
#include "content/ContentPack.hpp" #include "content/ContentPack.hpp"
#include "data/dynamic.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "files/engine_paths.hpp" #include "files/engine_paths.hpp"
#include "files/files.hpp" #include "files/files.hpp"
@ -130,7 +129,7 @@ static std::string assets_def_folder(AssetType tag) {
} }
void AssetsLoader::processPreload( void AssetsLoader::processPreload(
AssetType tag, const std::string& name, dynamic::Map* map AssetType tag, const std::string& name, const dv::value& map
) { ) {
std::string defFolder = assets_def_folder(tag); std::string defFolder = assets_def_folder(tag);
std::string path = defFolder + "/" + name; std::string path = defFolder + "/" + name;
@ -138,36 +137,34 @@ void AssetsLoader::processPreload(
add(tag, path, name); add(tag, path, name);
return; return;
} }
map->str("path", path); map.at("path").get(path);
switch (tag) { switch (tag) {
case AssetType::SOUND: case AssetType::SOUND: {
bool keepPCM = false;
add(tag, add(tag,
path, path,
name, name,
std::make_shared<SoundCfg>(map->get("keep-pcm", false))); std::make_shared<SoundCfg>(map.at("keep-pcm").get(keepPCM)));
break; break;
}
default: default:
add(tag, path, name); add(tag, path, name);
break; break;
} }
} }
void AssetsLoader::processPreloadList(AssetType tag, dynamic::List* list) { void AssetsLoader::processPreloadList(AssetType tag, const dv::value& list) {
if (list == nullptr) { if (list == nullptr) {
return; return;
} }
for (uint i = 0; i < list->size(); i++) { for (const auto& value : list) {
auto value = list->get(i); switch (value.getType()) {
switch (static_cast<dynamic::Type>(value.index())) { case dv::value_type::string:
case dynamic::Type::string: processPreload(tag, value.asString(), nullptr);
processPreload(tag, std::get<std::string>(value), nullptr);
break; break;
case dynamic::Type::map: { case dv::value_type::object:
auto map = std::get<dynamic::Map_sptr>(value); processPreload(tag, value["name"].asString(), value);
auto name = map->get<std::string>("name");
processPreload(tag, name, map.get());
break; break;
}
default: default:
throw std::runtime_error("invalid entry type"); throw std::runtime_error("invalid entry type");
} }
@ -176,12 +173,12 @@ void AssetsLoader::processPreloadList(AssetType tag, dynamic::List* list) {
void AssetsLoader::processPreloadConfig(const fs::path& file) { void AssetsLoader::processPreloadConfig(const fs::path& file) {
auto root = files::read_json(file); auto root = files::read_json(file);
processPreloadList(AssetType::ATLAS, root->list("atlases").get()); processPreloadList(AssetType::ATLAS, root["atlases"]);
processPreloadList(AssetType::FONT, root->list("fonts").get()); processPreloadList(AssetType::FONT, root["fonts"]);
processPreloadList(AssetType::SHADER, root->list("shaders").get()); processPreloadList(AssetType::SHADER, root["shaders"]);
processPreloadList(AssetType::TEXTURE, root->list("textures").get()); processPreloadList(AssetType::TEXTURE, root["textures"]);
processPreloadList(AssetType::SOUND, root->list("sounds").get()); processPreloadList(AssetType::SOUND, root["sounds"]);
processPreloadList(AssetType::MODEL, root->list("models").get()); processPreloadList(AssetType::MODEL, root["models"]);
// layouts are loaded automatically // layouts are loaded automatically
} }

View File

@ -12,11 +12,7 @@
#include "interfaces/Task.hpp" #include "interfaces/Task.hpp"
#include "typedefs.hpp" #include "typedefs.hpp"
#include "Assets.hpp" #include "Assets.hpp"
#include "data/dv.hpp"
namespace dynamic {
class Map;
class List;
}
class ResPaths; class ResPaths;
class AssetsLoader; class AssetsLoader;
@ -61,9 +57,9 @@ class AssetsLoader {
void tryAddSound(const std::string& name); void tryAddSound(const std::string& name);
void processPreload( void processPreload(
AssetType tag, const std::string& name, dynamic::Map* map AssetType tag, const std::string& name, const dv::value& map
); );
void processPreloadList(AssetType tag, dynamic::List* list); void processPreloadList(AssetType tag, const dv::value& list);
void processPreloadConfig(const std::filesystem::path& file); void processPreloadConfig(const std::filesystem::path& file);
void processPreloadConfigs(const Content* content); void processPreloadConfigs(const Content* content);
public: public:

View File

@ -11,7 +11,6 @@
#include "coders/json.hpp" #include "coders/json.hpp"
#include "coders/obj.hpp" #include "coders/obj.hpp"
#include "constants.hpp" #include "constants.hpp"
#include "data/dynamic.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "files/engine_paths.hpp" #include "files/engine_paths.hpp"
#include "files/files.hpp" #include "files/files.hpp"
@ -220,17 +219,17 @@ static void read_anim_file(
std::vector<std::pair<std::string, int>>& frameList std::vector<std::pair<std::string, int>>& frameList
) { ) {
auto root = files::read_json(animFile); auto root = files::read_json(animFile);
auto frameArr = root->list("frames");
float frameDuration = DEFAULT_FRAME_DURATION; float frameDuration = DEFAULT_FRAME_DURATION;
std::string frameName; std::string frameName;
if (frameArr) { if (auto found = root.at("frames")) {
for (size_t i = 0; i < frameArr->size(); i++) { auto& frameArr = *found;
auto currentFrame = frameArr->list(i); for (size_t i = 0; i < frameArr.size(); i++) {
auto currentFrame = frameArr[i];
frameName = currentFrame->str(0); frameName = currentFrame[0].asString();
if (currentFrame->size() > 1) { if (currentFrame.size() > 1) {
frameDuration = currentFrame->integer(1); frameDuration = currentFrame[1].asNumber();
} }
frameList.emplace_back(frameName, frameDuration); frameList.emplace_back(frameName, frameDuration);
} }

View File

@ -2,38 +2,38 @@
#include <stdexcept> #include <stdexcept>
#include "data/dynamic.hpp" #include "data/dv.hpp"
#include "byte_utils.hpp" #include "byte_utils.hpp"
#include "gzip.hpp" #include "gzip.hpp"
#include "util/Buffer.hpp"
using namespace json; using namespace json;
using namespace dynamic;
static void to_binary(ByteBuilder& builder, const Value& value) { static void to_binary(ByteBuilder& builder, const dv::value& value) {
switch (static_cast<Type>(value.index())) { switch (value.getType()) {
case Type::none: case dv::value_type::none:
throw std::runtime_error("none value is not implemented"); throw std::runtime_error("none value is not implemented");
case Type::map: { case dv::value_type::object: {
const auto bytes = to_binary(std::get<Map_sptr>(value).get()); const auto bytes = json::to_binary(value);
builder.put(bytes.data(), bytes.size()); builder.put(bytes.data(), bytes.size());
break; break;
} }
case Type::list: case dv::value_type::list:
builder.put(BJSON_TYPE_LIST); builder.put(BJSON_TYPE_LIST);
for (const auto& element : std::get<List_sptr>(value)->values) { for (const auto& element : value) {
to_binary(builder, element); to_binary(builder, element);
} }
builder.put(BJSON_END); builder.put(BJSON_END);
break; break;
case Type::bytes: { case dv::value_type::bytes: {
const auto& bytes = std::get<ByteBuffer_sptr>(value).get(); const auto& bytes = value.asBytes();
builder.put(BJSON_TYPE_BYTES); builder.put(BJSON_TYPE_BYTES);
builder.putInt32(bytes->size()); builder.putInt32(bytes.size());
builder.put(bytes->data(), bytes->size()); builder.put(bytes.data(), bytes.size());
break; break;
} }
case Type::integer: { case dv::value_type::integer: {
auto val = std::get<integer_t>(value); auto val = value.asInteger();
if (val >= 0 && val <= 255) { if (val >= 0 && val <= 255) {
builder.put(BJSON_TYPE_BYTE); builder.put(BJSON_TYPE_BYTE);
builder.put(val); builder.put(val);
@ -49,26 +49,23 @@ static void to_binary(ByteBuilder& builder, const Value& value) {
} }
break; break;
} }
case Type::number: case dv::value_type::number:
builder.put(BJSON_TYPE_NUMBER); builder.put(BJSON_TYPE_NUMBER);
builder.putFloat64(std::get<number_t>(value)); builder.putFloat64(value.asNumber());
break; break;
case Type::boolean: case dv::value_type::boolean:
builder.put(BJSON_TYPE_FALSE + std::get<bool>(value)); builder.put(BJSON_TYPE_FALSE + value.asBoolean());
break; break;
case Type::string: case dv::value_type::string:
builder.put(BJSON_TYPE_STRING); builder.put(BJSON_TYPE_STRING);
builder.put(std::get<std::string>(value)); builder.put(value.asString());
break; break;
} }
} }
static std::unique_ptr<List> array_from_binary(ByteReader& reader); std::vector<ubyte> json::to_binary(const dv::value& object, bool compress) {
static std::unique_ptr<Map> object_from_binary(ByteReader& reader);
std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
if (compress) { if (compress) {
auto bytes = to_binary(obj, false); auto bytes = to_binary(object, false);
return gzip::compress(bytes.data(), bytes.size()); return gzip::compress(bytes.data(), bytes.size());
} }
ByteBuilder builder; ByteBuilder builder;
@ -78,9 +75,9 @@ std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
builder.putInt32(0); builder.putInt32(0);
// writing entries // writing entries
for (auto& entry : obj->values) { for (const auto& [key, value] : object.asObject()) {
builder.putCStr(entry.first.c_str()); builder.putCStr(key.c_str());
to_binary(builder, entry.second); to_binary(builder, value);
} }
// terminating byte // terminating byte
builder.put(BJSON_END); builder.put(BJSON_END);
@ -90,27 +87,23 @@ std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
return builder.build(); return builder.build();
} }
std::vector<ubyte> json::to_binary(const Value& value, bool compress) { static dv::value list_from_binary(ByteReader& reader);
if (auto map = std::get_if<Map_sptr>(&value)) { static dv::value object_from_binary(ByteReader& reader);
return to_binary(map->get(), compress);
}
throw std::runtime_error("map is only supported as the root element");
}
static Value value_from_binary(ByteReader& reader) { static dv::value value_from_binary(ByteReader& reader) {
ubyte typecode = reader.get(); ubyte typecode = reader.get();
switch (typecode) { switch (typecode) {
case BJSON_TYPE_DOCUMENT: case BJSON_TYPE_DOCUMENT:
reader.getInt32(); reader.getInt32();
return Map_sptr(object_from_binary(reader).release()); return object_from_binary(reader);
case BJSON_TYPE_LIST: case BJSON_TYPE_LIST:
return List_sptr(array_from_binary(reader).release()); return list_from_binary(reader);
case BJSON_TYPE_BYTE: case BJSON_TYPE_BYTE:
return static_cast<integer_t>(reader.get()); return reader.get();
case BJSON_TYPE_INT16: case BJSON_TYPE_INT16:
return static_cast<integer_t>(reader.getInt16()); return reader.getInt16();
case BJSON_TYPE_INT32: case BJSON_TYPE_INT32:
return static_cast<integer_t>(reader.getInt32()); return reader.getInt32();
case BJSON_TYPE_INT64: case BJSON_TYPE_INT64:
return reader.getInt64(); return reader.getInt64();
case BJSON_TYPE_NUMBER: case BJSON_TYPE_NUMBER:
@ -121,7 +114,7 @@ static Value value_from_binary(ByteReader& reader) {
case BJSON_TYPE_STRING: case BJSON_TYPE_STRING:
return reader.getString(); return reader.getString();
case BJSON_TYPE_NULL: case BJSON_TYPE_NULL:
return NONE; return dv::none;
case BJSON_TYPE_BYTES: { case BJSON_TYPE_BYTES: {
int32_t size = reader.getInt32(); int32_t size = reader.getInt32();
if (size < 0) { if (size < 0) {
@ -132,7 +125,8 @@ static Value value_from_binary(ByteReader& reader) {
throw std::runtime_error( throw std::runtime_error(
"buffer_size > remaining_size "+std::to_string(size)); "buffer_size > remaining_size "+std::to_string(size));
} }
auto bytes = std::make_shared<ByteBuffer>(reader.pointer(), size); auto bytes = std::make_shared<util::Buffer<ubyte>>(
reader.pointer(), size);
reader.skip(size); reader.skip(size);
return bytes; return bytes;
} }
@ -141,26 +135,26 @@ static Value value_from_binary(ByteReader& reader) {
"type support not implemented for <"+std::to_string(typecode)+">"); "type support not implemented for <"+std::to_string(typecode)+">");
} }
static std::unique_ptr<List> array_from_binary(ByteReader& reader) { static dv::value list_from_binary(ByteReader& reader) {
auto array = std::make_unique<List>(); auto list = dv::list();
while (reader.peek() != BJSON_END) { while (reader.peek() != BJSON_END) {
array->put(value_from_binary(reader)); list.add(value_from_binary(reader));
} }
reader.get(); reader.get();
return array; return list;
} }
static std::unique_ptr<Map> object_from_binary(ByteReader& reader) { static dv::value object_from_binary(ByteReader& reader) {
auto obj = std::make_unique<Map>(); auto obj = dv::object();
while (reader.peek() != BJSON_END) { while (reader.peek() != BJSON_END) {
const char* key = reader.getCString(); const char* key = reader.getCString();
obj->put(key, value_from_binary(reader)); obj[key] = value_from_binary(reader);
} }
reader.get(); reader.get();
return obj; return obj;
} }
std::shared_ptr<Map> json::from_binary(const ubyte* src, size_t size) { dv::value json::from_binary(const ubyte* src, size_t size) {
if (size < 2) { if (size < 2) {
throw std::runtime_error("bytes length is less than 2"); throw std::runtime_error("bytes length is less than 2");
} }
@ -170,12 +164,6 @@ std::shared_ptr<Map> json::from_binary(const ubyte* src, size_t size) {
return from_binary(data.data(), data.size()); return from_binary(data.data(), data.size());
} else { } else {
ByteReader reader(src, size); ByteReader reader(src, size);
Value value = value_from_binary(reader); return value_from_binary(reader);
if (auto map = std::get_if<Map_sptr>(&value)) {
return *map;
} else {
throw std::runtime_error("root value is not an object");
}
} }
} }

View File

@ -4,11 +4,8 @@
#include <vector> #include <vector>
#include "data/dv.hpp" #include "data/dv.hpp"
#include "data/dynamic_fwd.hpp"
namespace dynamic { #include "typedefs.hpp"
class Map;
}
namespace json { namespace json {
inline constexpr int BJSON_END = 0x0; inline constexpr int BJSON_END = 0x0;
@ -26,15 +23,7 @@ namespace json {
inline constexpr int BJSON_TYPE_NULL = 0xC; inline constexpr int BJSON_TYPE_NULL = 0xC;
inline constexpr int BJSON_TYPE_CDOCUMENT = 0x1F; inline constexpr int BJSON_TYPE_CDOCUMENT = 0x1F;
std::vector<ubyte> to_binaryDV(const dv::value& obj, bool compress = false); std::vector<ubyte> to_binary(const dv::value& obj, bool compress = false);
dv::value from_binaryDV(const ubyte* src, size_t size); dv::value from_binary(const ubyte* src, size_t size);
std::vector<ubyte> to_binary(
const dynamic::Map* obj, bool compress = false
);
std::vector<ubyte> to_binary(
const dynamic::Value& obj, bool compress = false
);
std::shared_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
} }

View File

@ -1,168 +0,0 @@
#include "binary_json.hpp"
#include <stdexcept>
#include "data/dv.hpp"
#include "byte_utils.hpp"
#include "gzip.hpp"
using namespace json;
static void to_binary(ByteBuilder& builder, const dv::value& value) {
switch (value.getType()) {
case dv::value_type::none:
throw std::runtime_error("none value is not implemented");
case dv::value_type::object: {
const auto bytes = json::to_binaryDV(value);
builder.put(bytes.data(), bytes.size());
break;
}
case dv::value_type::list:
builder.put(BJSON_TYPE_LIST);
for (const auto& element : value) {
to_binary(builder, element);
}
builder.put(BJSON_END);
break;
case dv::value_type::bytes: {
const auto& bytes = value.asBytes();
builder.put(BJSON_TYPE_BYTES);
builder.putInt32(bytes.size());
builder.put(bytes.data(), bytes.size());
break;
}
case dv::value_type::integer: {
auto val = value.asInteger();
if (val >= 0 && val <= 255) {
builder.put(BJSON_TYPE_BYTE);
builder.put(val);
} else if (val >= INT16_MIN && val <= INT16_MAX) {
builder.put(BJSON_TYPE_INT16);
builder.putInt16(val);
} else if (val >= INT32_MIN && val <= INT32_MAX) {
builder.put(BJSON_TYPE_INT32);
builder.putInt32(val);
} else {
builder.put(BJSON_TYPE_INT64);
builder.putInt64(val);
}
break;
}
case dv::value_type::number:
builder.put(BJSON_TYPE_NUMBER);
builder.putFloat64(value.asNumber());
break;
case dv::value_type::boolean:
builder.put(BJSON_TYPE_FALSE + value.asBoolean());
break;
case dv::value_type::string:
builder.put(BJSON_TYPE_STRING);
builder.put(value.asString());
break;
}
}
std::vector<ubyte> json::to_binaryDV(const dv::value& object, bool compress) {
if (compress) {
auto bytes = to_binaryDV(object, false);
return gzip::compress(bytes.data(), bytes.size());
}
ByteBuilder builder;
// type byte
builder.put(BJSON_TYPE_DOCUMENT);
// document size
builder.putInt32(0);
// writing entries
for (const auto& [key, value] : object.asObject()) {
builder.putCStr(key.c_str());
to_binary(builder, value);
}
// terminating byte
builder.put(BJSON_END);
// updating document size
builder.setInt32(1, builder.size());
return builder.build();
}
static dv::value list_from_binary(ByteReader& reader);
static dv::value object_from_binary(ByteReader& reader);
static dv::value value_from_binary(ByteReader& reader) {
ubyte typecode = reader.get();
switch (typecode) {
case BJSON_TYPE_DOCUMENT:
reader.getInt32();
return object_from_binary(reader);
case BJSON_TYPE_LIST:
return list_from_binary(reader);
case BJSON_TYPE_BYTE:
return reader.get();
case BJSON_TYPE_INT16:
return reader.getInt16();
case BJSON_TYPE_INT32:
return reader.getInt32();
case BJSON_TYPE_INT64:
return reader.getInt64();
case BJSON_TYPE_NUMBER:
return reader.getFloat64();
case BJSON_TYPE_FALSE:
case BJSON_TYPE_TRUE:
return (typecode - BJSON_TYPE_FALSE) != 0;
case BJSON_TYPE_STRING:
return reader.getString();
case BJSON_TYPE_NULL:
return dv::none;
case BJSON_TYPE_BYTES: {
int32_t size = reader.getInt32();
if (size < 0) {
throw std::runtime_error(
"invalid byte-buffer size "+std::to_string(size));
}
if (size > reader.remaining()) {
throw std::runtime_error(
"buffer_size > remaining_size "+std::to_string(size));
}
auto bytes = std::make_shared<util::Buffer<ubyte>>(
reader.pointer(), size);
reader.skip(size);
return bytes;
}
}
throw std::runtime_error(
"type support not implemented for <"+std::to_string(typecode)+">");
}
static dv::value list_from_binary(ByteReader& reader) {
auto list = dv::list();
while (reader.peek() != BJSON_END) {
list.add(value_from_binary(reader));
}
reader.get();
return list;
}
static dv::value object_from_binary(ByteReader& reader) {
auto obj = dv::object();
while (reader.peek() != BJSON_END) {
const char* key = reader.getCString();
obj[key] = value_from_binary(reader);
}
reader.get();
return obj;
}
dv::value json::from_binaryDV(const ubyte* src, size_t size) {
if (size < 2) {
throw std::runtime_error("bytes length is less than 2");
}
if (src[0] == gzip::MAGIC[0] && src[1] == gzip::MAGIC[1]) {
// reading compressed document
auto data = gzip::decompress(src, size);
return from_binaryDV(data.data(), data.size());
} else {
ByteReader reader(src, size);
return value_from_binary(reader);
}
}

View File

@ -258,7 +258,7 @@ int64_t BasicParser::parseSimpleInt(int base) {
return value; return value;
} }
dynamic::Value BasicParser::parseNumber() { dv::value BasicParser::parseNumber() {
switch (peek()) { switch (peek()) {
case '-': case '-':
skip(1); skip(1);
@ -271,7 +271,7 @@ dynamic::Value BasicParser::parseNumber() {
} }
} }
dynamic::Value BasicParser::parseNumber(int sign) { dv::value BasicParser::parseNumber(int sign) {
char c = peek(); char c = peek();
int base = 10; int base = 10;
if (c == '0' && pos + 1 < source.length() && if (c == '0' && pos + 1 < source.length() &&

View File

@ -3,7 +3,7 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include "data/dynamic.hpp" #include "data/dv.hpp"
#include "typedefs.hpp" #include "typedefs.hpp"
inline int is_box(int c) { inline int is_box(int c) {
@ -90,8 +90,8 @@ protected:
void reset(); void reset();
int64_t parseSimpleInt(int base); int64_t parseSimpleInt(int base);
dynamic::Value parseNumber(int sign); dv::value parseNumber(int sign);
dynamic::Value parseNumber(); dv::value parseNumber();
std::string parseString(char chr, bool closeRequired = true); std::string parseString(char chr, bool closeRequired = true);
parsing_error error(const std::string& message); parsing_error error(const std::string& message);

View File

@ -6,29 +6,17 @@
#include <memory> #include <memory>
#include <sstream> #include <sstream>
#include "data/dynamic.hpp"
#include "util/stringutil.hpp" #include "util/stringutil.hpp"
#include "commons.hpp" #include "commons.hpp"
using namespace json; using namespace json;
using namespace dynamic;
class Parser : BasicParser { class Parser : BasicParser {
std::unique_ptr<dynamic::List> parseList();
std::unique_ptr<dynamic::Map> parseObject();
dynamic::Value parseValue();
public:
Parser(std::string_view filename, std::string_view source);
std::unique_ptr<dynamic::Map> parse();
};
class ParserDV : BasicParser {
dv::value parseList(); dv::value parseList();
dv::value parseObject(); dv::value parseObject();
dv::value parseValue(); dv::value parseValue();
public: public:
ParserDV(std::string_view filename, std::string_view source); Parser(std::string_view filename, std::string_view source);
dv::value parse(); dv::value parse();
}; };
@ -46,22 +34,6 @@ inline void newline(
} }
} }
void stringifyObj(
const Map* obj,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
);
void stringifyArr(
const List* list,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
);
void stringifyObj( void stringifyObj(
const dv::value& obj, const dv::value& obj,
std::stringstream& ss, std::stringstream& ss,
@ -78,34 +50,6 @@ void stringifyList(
bool nice bool nice
); );
void stringifyValue(
const Value& value,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
) {
if (auto map = std::get_if<Map_sptr>(&value)) {
stringifyObj(map->get(), ss, indent, indentstr, nice);
} else if (auto listptr = std::get_if<List_sptr>(&value)) {
stringifyArr(listptr->get(), ss, indent, indentstr, nice);
} else if (auto bytesptr = std::get_if<ByteBuffer_sptr>(&value)) {
auto bytes = bytesptr->get();
ss << "\"" << util::base64_encode(bytes->data(), bytes->size());
ss << "\"";
} else if (auto flag = std::get_if<bool>(&value)) {
ss << (*flag ? "true" : "false");
} else if (auto num = std::get_if<number_t>(&value)) {
ss << std::setprecision(15) << *num;
} else if (auto num = std::get_if<integer_t>(&value)) {
ss << *num;
} else if (auto str = std::get_if<std::string>(&value)) {
ss << util::escape(*str);
} else {
ss << "null";
}
}
void stringifyValue( void stringifyValue(
const dv::value& value, const dv::value& value,
std::stringstream& ss, std::stringstream& ss,
@ -146,74 +90,6 @@ void stringifyValue(
} }
} }
void stringifyArr(
const List* list,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
) {
if (list == nullptr) {
ss << "nullptr";
return;
}
if (list->values.empty()) {
ss << "[]";
return;
}
ss << "[";
for (size_t i = 0; i < list->size(); i++) {
if (i > 0 || nice) {
newline(ss, nice, indent, indentstr);
}
const Value& value = list->values[i];
stringifyValue(value, ss, indent + 1, indentstr, nice);
if (i + 1 < list->size()) {
ss << ',';
}
}
if (nice) {
newline(ss, true, indent - 1, indentstr);
}
ss << ']';
}
void stringifyObj(
const Map* obj,
std::stringstream& ss,
int indent,
const std::string& indentstr,
bool nice
) {
if (obj == nullptr) {
ss << "nullptr";
return;
}
if (obj->values.empty()) {
ss << "{}";
return;
}
ss << "{";
size_t index = 0;
for (auto& entry : obj->values) {
const std::string& key = entry.first;
if (index > 0 || nice) {
newline(ss, nice, indent, indentstr);
}
const Value& value = entry.second;
ss << util::escape(key) << ": ";
stringifyValue(value, ss, indent + 1, indentstr, nice);
index++;
if (index < obj->values.size()) {
ss << ',';
}
}
if (nice) {
newline(ss, true, indent - 1, indentstr);
}
ss << '}';
}
void stringifyList( void stringifyList(
const dv::value& list, const dv::value& list,
std::stringstream& ss, std::stringstream& ss,
@ -273,30 +149,6 @@ void stringifyObj(
} }
std::string json::stringify( std::string json::stringify(
const Map* obj, bool nice, const std::string& indent
) {
std::stringstream ss;
stringifyObj(obj, ss, 1, indent, nice);
return ss.str();
}
std::string json::stringify(
const dynamic::List* arr, bool nice, const std::string& indent
) {
std::stringstream ss;
stringifyArr(arr, ss, 1, indent, nice);
return ss.str();
}
std::string json::stringify(
const dynamic::Value& value, bool nice, const std::string& indent
) {
std::stringstream ss;
stringifyValue(value, ss, 1, indent, nice);
return ss.str();
}
std::string json::stringifyDV(
const dv::value& value, bool nice, const std::string& indent const dv::value& value, bool nice, const std::string& indent
) { ) {
std::stringstream ss; std::stringstream ss;
@ -308,7 +160,7 @@ Parser::Parser(std::string_view filename, std::string_view source)
: BasicParser(filename, source) { : BasicParser(filename, source) {
} }
std::unique_ptr<Map> Parser::parse() { dv::value Parser::parse() {
char next = peek(); char next = peek();
if (next != '{') { if (next != '{') {
throw error("'{' expected"); throw error("'{' expected");
@ -316,118 +168,7 @@ std::unique_ptr<Map> Parser::parse() {
return parseObject(); return parseObject();
} }
std::unique_ptr<Map> Parser::parseObject() { dv::value Parser::parseObject() {
expect('{');
auto obj = std::make_unique<Map>();
auto& map = obj->values;
while (peek() != '}') {
if (peek() == '#') {
skipLine();
continue;
}
std::string key = parseName();
char next = peek();
if (next != ':') {
throw error("':' expected");
}
pos++;
map.insert(std::make_pair(key, parseValue()));
next = peek();
if (next == ',') {
pos++;
} else if (next == '}') {
break;
} else {
throw error("',' expected");
}
}
pos++;
return obj;
}
std::unique_ptr<List> Parser::parseList() {
expect('[');
auto arr = std::make_unique<List>();
auto& values = arr->values;
while (peek() != ']') {
if (peek() == '#') {
skipLine();
continue;
}
values.push_back(parseValue());
char next = peek();
if (next == ',') {
pos++;
} else if (next == ']') {
break;
} else {
throw error("',' expected");
}
}
pos++;
return arr;
}
Value Parser::parseValue() {
char next = peek();
if (next == '-' || next == '+' || is_digit(next)) {
auto numeric = parseNumber();
if (std::holds_alternative<integer_t>(numeric)) {
return std::get<integer_t>(numeric);
}
return std::get<number_t>(numeric);
}
if (is_identifier_start(next)) {
std::string literal = parseName();
if (literal == "true") {
return true;
} else if (literal == "false") {
return false;
} else if (literal == "inf") {
return INFINITY;
} else if (literal == "nan") {
return NAN;
}
throw error("invalid literal ");
}
if (next == '{') {
return Map_sptr(parseObject().release());
}
if (next == '[') {
return List_sptr(parseList().release());
}
if (next == '"' || next == '\'') {
pos++;
return parseString(next);
}
throw error("unexpected character '" + std::string({next}) + "'");
}
dynamic::Map_sptr json::parse(
std::string_view filename, std::string_view source
) {
Parser parser(filename, source);
return parser.parse();
}
dynamic::Map_sptr json::parse(std::string_view source) {
return parse("<string>", source);
}
ParserDV::ParserDV(std::string_view filename, std::string_view source)
: BasicParser(filename, source) {
}
dv::value ParserDV::parse() {
char next = peek();
if (next != '{') {
throw error("'{' expected");
}
return parseObject();
}
dv::value ParserDV::parseObject() {
expect('{'); expect('{');
auto object = dv::object(); auto object = dv::object();
while (peek() != '}') { while (peek() != '}') {
@ -455,7 +196,7 @@ dv::value ParserDV::parseObject() {
return object; return object;
} }
dv::value ParserDV::parseList() { dv::value Parser::parseList() {
expect('['); expect('[');
auto list = dv::list(); auto list = dv::list();
while (peek() != ']') { while (peek() != ']') {
@ -478,14 +219,14 @@ dv::value ParserDV::parseList() {
return list; return list;
} }
dv::value ParserDV::parseValue() { dv::value Parser::parseValue() {
char next = peek(); char next = peek();
if (next == '-' || next == '+' || is_digit(next)) { if (next == '-' || next == '+' || is_digit(next)) {
auto numeric = parseNumber(); auto numeric = parseNumber();
if (std::holds_alternative<integer_t>(numeric)) { if (numeric.isInteger()) {
return std::get<integer_t>(numeric); return numeric.asInteger();
} }
return std::get<number_t>(numeric); return numeric.asNumber();
} }
if (is_identifier_start(next)) { if (is_identifier_start(next)) {
std::string literal = parseName(); std::string literal = parseName();
@ -513,13 +254,13 @@ dv::value ParserDV::parseValue() {
throw error("unexpected character '" + std::string({next}) + "'"); throw error("unexpected character '" + std::string({next}) + "'");
} }
dv::value json::parseDV( dv::value json::parse(
std::string_view filename, std::string_view source std::string_view filename, std::string_view source
) { ) {
ParserDV parser(filename, source); Parser parser(filename, source);
return parser.parse(); return parser.parse();
} }
dv::value json::parseDV(std::string_view source) { dv::value json::parse(std::string_view source) {
return parseDV("<string>", source); return parse("<string>", source);
} }

View File

@ -2,31 +2,15 @@
#include <string> #include <string>
#include "data/dynamic.hpp"
#include "data/dv.hpp" #include "data/dv.hpp"
#include "typedefs.hpp" #include "typedefs.hpp"
#include "binary_json.hpp" #include "binary_json.hpp"
namespace json { namespace json {
dynamic::Map_sptr parse(std::string_view filename, std::string_view source); dv::value parse(std::string_view filename, std::string_view source);
dynamic::Map_sptr parse(std::string_view source); dv::value parse(std::string_view source);
dv::value parseDV(std::string_view filename, std::string_view source);
dv::value parseDV(std::string_view source);
std::string stringify( std::string stringify(
const dynamic::Map* obj, bool nice, const std::string& indent
);
std::string stringify(
const dynamic::List* arr, bool nice, const std::string& indent
);
std::string stringify(
const dynamic::Value& value, bool nice, const std::string& indent
);
std::string stringifyDV(
const dv::value& value, bool nice, const std::string& indent=" " const dv::value& value, bool nice, const std::string& indent=" "
); );
} }

View File

@ -63,18 +63,18 @@ public:
} }
auto cmd = parseName(); auto cmd = parseName();
if (cmd == "v") { if (cmd == "v") {
float x = dynamic::as_number(parseNumber()); float x = parseNumber().asNumber();
float y = dynamic::as_number(parseNumber()); float y = parseNumber().asNumber();
float z = dynamic::as_number(parseNumber()); float z = parseNumber().asNumber();
coords.emplace_back(x, y, z); coords.emplace_back(x, y, z);
} else if (cmd == "vt") { } else if (cmd == "vt") {
float u = dynamic::as_number(parseNumber()); float u = parseNumber().asNumber();
float v = dynamic::as_number(parseNumber()); float v = parseNumber().asNumber();
uvs.emplace_back(u, v); uvs.emplace_back(u, v);
} else if (cmd == "vn") { } else if (cmd == "vn") {
float x = dynamic::as_number(parseNumber()); float x = parseNumber().asNumber();
float y = dynamic::as_number(parseNumber()); float y = parseNumber().asNumber();
float z = dynamic::as_number(parseNumber()); float z = parseNumber().asNumber();
normals.emplace_back(x, y, z); normals.emplace_back(x, y, z);
} else { } else {
skipLine(); skipLine();

View File

@ -6,7 +6,6 @@
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include "data/dynamic.hpp"
#include "data/setting.hpp" #include "data/setting.hpp"
#include "files/settings_io.hpp" #include "files/settings_io.hpp"
#include "util/stringutil.hpp" #include "util/stringutil.hpp"
@ -15,7 +14,7 @@
using namespace toml; using namespace toml;
class TomlReader : BasicParser { class TomlReader : BasicParser {
dynamic::Map_sptr root; dv::value root;
void skipWhitespace() override { void skipWhitespace() override {
BasicParser::skipWhitespace(); BasicParser::skipWhitespace();
@ -27,33 +26,33 @@ class TomlReader : BasicParser {
} }
} }
dynamic::Map& getSection(const std::string& section) { dv::value& getSection(const std::string& section) {
if (section.empty()) { if (section.empty()) {
return *root; return root;
} }
size_t offset = 0; size_t offset = 0;
auto& rootMap = *root; auto rootMap = &root;
do { do {
size_t index = section.find('.', offset); size_t index = section.find('.', offset);
if (index == std::string::npos) { if (index == std::string::npos) {
auto map = rootMap.map(section); auto map = rootMap->at(section);
if (map == nullptr) { if (!map) {
return rootMap.putMap(section); return rootMap->object(section);
} }
return *map; return *map;
} }
auto subsection = section.substr(offset, index); auto subsection = section.substr(offset, index);
auto map = rootMap.map(subsection); auto map = rootMap->at(subsection);
if (map == nullptr) { if (!map) {
rootMap = rootMap.putMap(subsection); rootMap = &rootMap->object(subsection);
} else { } else {
rootMap = *map; rootMap = &*map;
} }
offset = index + 1; offset = index + 1;
} while (true); } while (true);
} }
void readSection(const std::string& section, dynamic::Map& map) { void readSection(const std::string& section, dv::value& map) {
while (hasNext()) { while (hasNext()) {
skipWhitespace(); skipWhitespace();
if (!hasNext()) { if (!hasNext()) {
@ -71,23 +70,23 @@ class TomlReader : BasicParser {
expect('='); expect('=');
c = peek(); c = peek();
if (is_digit(c)) { if (is_digit(c)) {
map.put(name, parseNumber(1)); map[name] = parseNumber(1);
} else if (c == '-' || c == '+') { } else if (c == '-' || c == '+') {
int sign = c == '-' ? -1 : 1; int sign = c == '-' ? -1 : 1;
pos++; pos++;
map.put(name, parseNumber(sign)); map[name] = parseNumber(sign);
} else if (is_identifier_start(c)) { } else if (is_identifier_start(c)) {
std::string identifier = parseName(); std::string identifier = parseName();
if (identifier == "true" || identifier == "false") { if (identifier == "true" || identifier == "false") {
map.put(name, identifier == "true"); map[name] = identifier == "true";
} else if (identifier == "inf") { } else if (identifier == "inf") {
map.put(name, INFINITY); map[name] = INFINITY;
} else if (identifier == "nan") { } else if (identifier == "nan") {
map.put(name, NAN); map[name] = NAN;
} }
} else if (c == '"' || c == '\'') { } else if (c == '"' || c == '\'') {
pos++; pos++;
map.put(name, parseString(c)); map[name] = parseString(c);
} else { } else {
throw error("feature is not supported"); throw error("feature is not supported");
} }
@ -97,36 +96,28 @@ class TomlReader : BasicParser {
public: public:
TomlReader(std::string_view file, std::string_view source) TomlReader(std::string_view file, std::string_view source)
: BasicParser(file, source) { : BasicParser(file, source) {
root = dynamic::create_map(); root = dv::object();
} }
dynamic::Map_sptr read() { dv::value read() {
skipWhitespace(); skipWhitespace();
if (!hasNext()) { if (!hasNext()) {
return root; return root;
} }
readSection("", *root); readSection("", root);
return root; return root;
} }
}; };
dynamic::Map_sptr toml::parse(std::string_view file, std::string_view source) {
return TomlReader(file, source).read();
}
void toml::parse( void toml::parse(
SettingsHandler& handler, std::string_view file, std::string_view source SettingsHandler& handler, std::string_view file, std::string_view source
) { ) {
auto map = parse(file, source); auto map = parse(file, source);
for (auto& entry : map->values) { for (const auto& [sectionName, sectionMap] : map.asObject()) {
const auto& sectionName = entry.first; if (!sectionMap.isObject()) {
auto sectionMap = std::get_if<dynamic::Map_sptr>(&entry.second);
if (sectionMap == nullptr) {
continue; continue;
} }
for (auto& sectionEntry : (*sectionMap)->values) { for (const auto& [name, value] : sectionMap.asObject()) {
const auto& name = sectionEntry.first;
auto& value = sectionEntry.second;
auto fullname = sectionName + "." + name; auto fullname = sectionName + "." + name;
if (handler.has(fullname)) { if (handler.has(fullname)) {
handler.setValue(fullname, value); handler.setValue(fullname, value);
@ -135,24 +126,24 @@ void toml::parse(
} }
} }
std::string toml::stringify(dynamic::Map& root, const std::string& name) { dv::value toml::parse(std::string_view file, std::string_view source) {
return TomlReader(file, source).read();
}
std::string toml::stringify(const dv::value& root, const std::string& name) {
std::stringstream ss; std::stringstream ss;
if (!name.empty()) { if (!name.empty()) {
ss << "[" << name << "]\n"; ss << "[" << name << "]\n";
} }
for (auto& entry : root.values) { for (const auto& [key, value] : root.asObject()) {
if (!std::holds_alternative<dynamic::Map_sptr>(entry.second)) { if (!value.isObject()) {
ss << entry.first << " = "; ss << key << " = " << value << "\n";
ss << entry.second << "\n";
} }
} }
for (auto& entry : root.values) { for (const auto& [key, value] : root.asObject()) {
if (auto submap = std::get_if<dynamic::Map_sptr>(&entry.second)) { if (value.isObject()) {
ss << "\n" ss << "\n" << toml::stringify(value,
<< toml::stringify( name.empty() ? key : name + "." + key);
**submap,
name.empty() ? entry.first : name + "." + entry.first
);
} }
} }
return ss.str(); return ss.str();

View File

@ -2,14 +2,15 @@
#include <string> #include <string>
#include "data/dynamic.hpp" #include "data/dv.hpp"
class SettingsHandler; class SettingsHandler;
namespace toml { namespace toml {
std::string stringify(SettingsHandler& handler); std::string stringify(SettingsHandler& handler);
std::string stringify(dynamic::Map& root, const std::string& name = ""); std::string stringify(const dv::value& root, const std::string& name = "");
dynamic::Map_sptr parse(std::string_view file, std::string_view source);
dv::value parse(std::string_view file, std::string_view source);
void parse( void parse(
SettingsHandler& handler, std::string_view file, std::string_view source SettingsHandler& handler, std::string_view file, std::string_view source

View File

@ -8,8 +8,8 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "data/dynamic_fwd.hpp"
#include "content_fwd.hpp" #include "content_fwd.hpp"
#include "data/dv.hpp"
using DrawGroups = std::set<ubyte>; using DrawGroups = std::set<ubyte>;
template <class K, class V> template <class K, class V>
@ -122,18 +122,18 @@ public:
class ResourceIndices { class ResourceIndices {
std::vector<std::string> names; std::vector<std::string> names;
std::unordered_map<std::string, size_t> indices; std::unordered_map<std::string, size_t> indices;
std::unique_ptr<std::vector<dynamic::Map_sptr>> savedData; std::unique_ptr<std::vector<dv::value>> savedData;
public: public:
ResourceIndices() ResourceIndices()
: savedData(std::make_unique<std::vector<dynamic::Map_sptr>>()) { : savedData(std::make_unique<std::vector<dv::value>>()) {
} }
static constexpr size_t MISSING = SIZE_MAX; static constexpr size_t MISSING = SIZE_MAX;
void add(std::string name, dynamic::Map_sptr map) { void add(std::string name, dv::value map) {
indices[name] = names.size(); indices[name] = names.size();
names.push_back(name); names.push_back(name);
savedData->push_back(map); savedData->push_back(std::move(map));
} }
const std::string& getName(size_t index) const { const std::string& getName(size_t index) const {
@ -148,12 +148,12 @@ public:
return MISSING; return MISSING;
} }
dynamic::Map_sptr getSavedData(size_t index) const { dv::value getSavedData(size_t index) const {
return savedData->at(index); return savedData->at(index);
} }
void saveData(size_t index, dynamic::Map_sptr map) const { void saveData(size_t index, dv::value map) const {
savedData->at(index) = map; savedData->at(index) = std::move(map);
} }
size_t size() const { size_t size() const {

View File

@ -20,9 +20,11 @@ ContentLUT::ContentLUT(
template <class T> template <class T>
static constexpr size_t get_entries_count( static constexpr size_t get_entries_count(
const ContentUnitIndices<T>& indices, const dynamic::List_sptr& list const ContentUnitIndices<T>& indices, const dv::value& list
) { ) {
return list ? std::max(list->size(), indices.count()) : indices.count(); return list != nullptr
? std::max(list.size(), indices.count())
: indices.count();
} }
std::shared_ptr<ContentLUT> ContentLUT::create( std::shared_ptr<ContentLUT> ContentLUT::create(
@ -36,8 +38,8 @@ std::shared_ptr<ContentLUT> ContentLUT::create(
} }
auto root = files::read_json(filename); auto root = files::read_json(filename);
auto blocklist = root->list("blocks"); auto& blocklist = root["blocks"];
auto itemlist = root->list("items"); auto& itemlist = root["items"];
auto* indices = content->getIndices(); auto* indices = content->getIndices();
size_t blocks_c = get_entries_count(indices->blocks, blocklist); size_t blocks_c = get_entries_count(indices->blocks, blocklist);
@ -45,8 +47,8 @@ std::shared_ptr<ContentLUT> ContentLUT::create(
auto lut = std::make_shared<ContentLUT>(indices, blocks_c, items_c); auto lut = std::make_shared<ContentLUT>(indices, blocks_c, items_c);
lut->blocks.setup(blocklist.get(), content->blocks); lut->blocks.setup(blocklist, content->blocks);
lut->items.setup(itemlist.get(), content->items); lut->items.setup(itemlist, content->items);
if (lut->hasContentReorder() || lut->hasMissingContent()) { if (lut->hasContentReorder() || lut->hasMissingContent()) {
return lut; return lut;

View File

@ -6,7 +6,7 @@
#include <vector> #include <vector>
#include "constants.hpp" #include "constants.hpp"
#include "data/dynamic.hpp" #include "data/dv.hpp"
#include "typedefs.hpp" #include "typedefs.hpp"
#include "Content.hpp" #include "Content.hpp"
@ -45,10 +45,10 @@ public:
names.emplace_back(""); names.emplace_back("");
} }
} }
void setup(dynamic::List* list, const ContentUnitDefs<U>& defs) { void setup(const dv::value& list, const ContentUnitDefs<U>& defs) {
if (list) { if (list != nullptr) {
for (size_t i = 0; i < list->size(); i++) { for (size_t i = 0; i < list.size(); i++) {
std::string name = list->str(i); const std::string& name = list[i].asString();
if (auto def = defs.find(name)) { if (auto def = defs.find(name)) {
set(i, name, def->rt.id); set(i, name, def->rt.id);
} else { } else {

View File

@ -11,7 +11,6 @@
#include "ContentPack.hpp" #include "ContentPack.hpp"
#include "coders/json.hpp" #include "coders/json.hpp"
#include "core_defs.hpp" #include "core_defs.hpp"
#include "data/dynamic.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "files/files.hpp" #include "files/files.hpp"
#include "items/ItemDef.hpp" #include "items/ItemDef.hpp"
@ -21,6 +20,7 @@
#include "util/listutil.hpp" #include "util/listutil.hpp"
#include "util/stringutil.hpp" #include "util/stringutil.hpp"
#include "voxels/Block.hpp" #include "voxels/Block.hpp"
#include "data/dv_util.hpp"
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -60,7 +60,7 @@ static void detect_defs(
bool ContentLoader::fixPackIndices( bool ContentLoader::fixPackIndices(
const fs::path& folder, const fs::path& folder,
dynamic::Map* indicesRoot, dv::value& indicesRoot,
const std::string& contentSection const std::string& contentSection
) { ) {
std::vector<std::string> detected; std::vector<std::string> detected;
@ -68,25 +68,23 @@ bool ContentLoader::fixPackIndices(
std::vector<std::string> indexed; std::vector<std::string> indexed;
bool modified = false; bool modified = false;
if (!indicesRoot->has(contentSection)) { if (!indicesRoot.has(contentSection)) {
indicesRoot->putList(contentSection); indicesRoot.list(contentSection);
} }
auto arr = indicesRoot->list(contentSection); auto& arr = indicesRoot[contentSection];
if (arr) { for (size_t i = 0; i < arr.size(); i++) {
for (uint i = 0; i < arr->size(); i++) { const std::string& name = arr[i].asString();
std::string name = arr->str(i); if (!util::contains(detected, name)) {
if (!util::contains(detected, name)) { arr.erase(i);
arr->remove(i); i--;
i--; modified = true;
modified = true; continue;
continue;
}
indexed.push_back(name);
} }
indexed.push_back(name);
} }
for (auto name : detected) { for (auto name : detected) {
if (!util::contains(indexed, name)) { if (!util::contains(indexed, name)) {
arr->put(name); arr.add(name);
modified = true; modified = true;
} }
} }
@ -100,21 +98,21 @@ void ContentLoader::fixPackIndices() {
auto itemsFolder = folder / ContentPack::ITEMS_FOLDER; auto itemsFolder = folder / ContentPack::ITEMS_FOLDER;
auto entitiesFolder = folder / ContentPack::ENTITIES_FOLDER; auto entitiesFolder = folder / ContentPack::ENTITIES_FOLDER;
dynamic::Map_sptr root; dv::value root;
if (fs::is_regular_file(indexFile)) { if (fs::is_regular_file(indexFile)) {
root = files::read_json(indexFile); root = files::read_json(indexFile);
} else { } else {
root = dynamic::create_map(); root = dv::object();
} }
bool modified = false; bool modified = false;
modified |= fixPackIndices(blocksFolder, root.get(), "blocks"); modified |= fixPackIndices(blocksFolder, root, "blocks");
modified |= fixPackIndices(itemsFolder, root.get(), "items"); modified |= fixPackIndices(itemsFolder, root, "items");
modified |= fixPackIndices(entitiesFolder, root.get(), "entities"); modified |= fixPackIndices(entitiesFolder, root, "entities");
if (modified) { if (modified) {
// rewrite modified json // rewrite modified json
files::write_json(indexFile, root.get()); files::write_json(indexFile, root);
} }
} }
@ -123,9 +121,8 @@ void ContentLoader::loadBlock(
) { ) {
auto root = files::read_json(file); auto root = files::read_json(file);
if (root->has("parent")) { if (root.has("parent")) {
std::string parentName; const auto& parentName = root["parent"].asString();
root->str("parent", parentName);
auto parentDef = this->builder.blocks.get(parentName); auto parentDef = this->builder.blocks.get(parentName);
if (parentDef == nullptr) { if (parentDef == nullptr) {
throw std::runtime_error( throw std::runtime_error(
@ -135,29 +132,28 @@ void ContentLoader::loadBlock(
parentDef->cloneTo(def); parentDef->cloneTo(def);
} }
root->str("caption", def.caption); root.at("caption").get(def.caption);
// block texturing // block texturing
if (root->has("texture")) { if (root.has("texture")) {
std::string texture; const auto& texture = root["texture"].asString();
root->str("texture", texture);
for (uint i = 0; i < 6; i++) { for (uint i = 0; i < 6; i++) {
def.textureFaces[i] = texture; def.textureFaces[i] = texture;
} }
} else if (root->has("texture-faces")) { } else if (root.has("texture-faces")) {
auto texarr = root->list("texture-faces"); const auto& texarr = root["texture-faces"];
for (uint i = 0; i < 6; i++) { for (uint i = 0; i < 6; i++) {
def.textureFaces[i] = texarr->str(i); def.textureFaces[i] = texarr[i].asString();
} }
} }
// block model // block model
std::string modelName; std::string modelName;
root->str("model", modelName); root.at("model").get(modelName);
if (auto model = BlockModel_from(modelName)) { if (auto model = BlockModel_from(modelName)) {
if (*model == BlockModel::custom) { if (*model == BlockModel::custom) {
if (root->has("model-primitives")) { if (root.has("model-primitives")) {
loadCustomBlockModel(def, root->map("model-primitives").get()); loadCustomBlockModel(def, root["model-primitives"]);
} else { } else {
logger.error() << name << ": no 'model-primitives' found"; logger.error() << name << ": no 'model-primitives' found";
} }
@ -168,11 +164,12 @@ void ContentLoader::loadBlock(
def.model = BlockModel::none; def.model = BlockModel::none;
} }
root->str("material", def.material); root.at("material").get(def.material);
// rotation profile // rotation profile
std::string profile = "none"; std::string profile = "none";
root->str("rotation", profile); root.at("rotation").get(profile);
def.rotatable = profile != "none"; def.rotatable = profile != "none";
if (profile == BlockRotProfile::PIPE_NAME) { if (profile == BlockRotProfile::PIPE_NAME) {
def.rotations = BlockRotProfile::PIPE; def.rotations = BlockRotProfile::PIPE;
@ -184,20 +181,29 @@ void ContentLoader::loadBlock(
} }
// block hitbox AABB [x, y, z, width, height, depth] // block hitbox AABB [x, y, z, width, height, depth]
auto boxarr = root->list("hitboxes"); if (auto found = root.at("hitboxes")) {
if (boxarr) { const auto& boxarr = *found;
def.hitboxes.resize(boxarr->size()); def.hitboxes.resize(boxarr.size());
for (uint i = 0; i < boxarr->size(); i++) { for (uint i = 0; i < boxarr.size(); i++) {
auto box = boxarr->list(i); const auto& box = boxarr[i];
auto& hitboxesIndex = def.hitboxes[i]; auto& hitboxesIndex = def.hitboxes[i];
hitboxesIndex.a = glm::vec3(box->num(0), box->num(1), box->num(2)); hitboxesIndex.a = glm::vec3(
hitboxesIndex.b = glm::vec3(box->num(3), box->num(4), box->num(5)); box[0].asNumber(), box[1].asNumber(), box[2].asNumber()
);
hitboxesIndex.b = glm::vec3(
box[3].asNumber(), box[4].asNumber(), box[5].asNumber()
);
hitboxesIndex.b += hitboxesIndex.a; hitboxesIndex.b += hitboxesIndex.a;
} }
} else if ((boxarr = root->list("hitbox"))) { } else if (auto found = root.at("hitbox")) {
const auto& box = *found;
AABB aabb; AABB aabb;
aabb.a = glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2)); aabb.a = glm::vec3(
aabb.b = glm::vec3(boxarr->num(3), boxarr->num(4), boxarr->num(5)); box[0].asNumber(), box[1].asNumber(), box[2].asNumber()
);
aabb.b = glm::vec3(
box[3].asNumber(), box[4].asNumber(), box[5].asNumber()
);
aabb.b += aabb.a; aabb.b += aabb.a;
def.hitboxes = {aabb}; def.hitboxes = {aabb};
} else if (!def.modelBoxes.empty()) { } else if (!def.modelBoxes.empty()) {
@ -207,17 +213,19 @@ void ContentLoader::loadBlock(
} }
// block light emission [r, g, b] where r,g,b in range [0..15] // block light emission [r, g, b] where r,g,b in range [0..15]
if (auto emissionarr = root->list("emission")) { if (auto found = root.at("emission")) {
def.emission[0] = emissionarr->num(0); const auto& emissionarr = *found;
def.emission[1] = emissionarr->num(1); def.emission[0] = emissionarr[0].asNumber();
def.emission[2] = emissionarr->num(2); def.emission[1] = emissionarr[1].asNumber();
def.emission[2] = emissionarr[2].asNumber();
} }
// block size // block size
if (auto sizearr = root->list("size")) { if (auto found = root.at("size")) {
def.size.x = sizearr->num(0); const auto& sizearr = *found;
def.size.y = sizearr->num(1); def.size.x = sizearr[0].asNumber();
def.size.z = sizearr->num(2); def.size.y = sizearr[1].asNumber();
def.size.z = sizearr[2].asNumber();
if (def.model == BlockModel::block && if (def.model == BlockModel::block &&
(def.size.x != 1 || def.size.y != 1 || def.size.z != 1)) { (def.size.x != 1 || def.size.y != 1 || def.size.z != 1)) {
def.model = BlockModel::aabb; def.model = BlockModel::aabb;
@ -226,22 +234,22 @@ void ContentLoader::loadBlock(
} }
// primitive properties // primitive properties
root->flag("obstacle", def.obstacle); root.at("obstacle").get(def.obstacle);
root->flag("replaceable", def.replaceable); root.at("replaceable").get(def.replaceable);
root->flag("light-passing", def.lightPassing); root.at("light-passing").get(def.lightPassing);
root->flag("sky-light-passing", def.skyLightPassing); root.at("sky-light-passing").get(def.skyLightPassing);
root->flag("shadeless", def.shadeless); root.at("shadeless").get(def.shadeless);
root->flag("ambient-occlusion", def.ambientOcclusion); root.at("ambient-occlusion").get(def.ambientOcclusion);
root->flag("breakable", def.breakable); root.at("breakable").get(def.breakable);
root->flag("selectable", def.selectable); root.at("selectable").get(def.selectable);
root->flag("grounded", def.grounded); root.at("grounded").get(def.grounded);
root->flag("hidden", def.hidden); root.at("hidden").get(def.hidden);
root->num("draw-group", def.drawGroup); root.at("draw-group").get(def.drawGroup);
root->str("picking-item", def.pickingItem); root.at("picking-item").get(def.pickingItem);
root->str("script-name", def.scriptName); root.at("script-name").get(def.scriptName);
root->str("ui-layout", def.uiLayout); root.at("ui-layout").get(def.uiLayout);
root->num("inventory-size", def.inventorySize); root.at("inventory-size").get(def.inventorySize);
root->num("tick-interval", def.tickInterval); root.at("tick-interval").get(def.tickInterval);
if (def.tickInterval == 0) { if (def.tickInterval == 0) {
def.tickInterval = 1; def.tickInterval = 1;
} }
@ -251,48 +259,57 @@ void ContentLoader::loadBlock(
} }
} }
void ContentLoader::loadCustomBlockModel(Block& def, dynamic::Map* primitives) { void ContentLoader::loadCustomBlockModel(Block& def, const dv::value& primitives) {
if (primitives->has("aabbs")) { if (primitives.has("aabbs")) {
auto modelboxes = primitives->list("aabbs"); const auto& modelboxes = primitives["aabbs"];
for (uint i = 0; i < modelboxes->size(); i++) { for (uint i = 0; i < modelboxes.size(); i++) {
/* Parse aabb */ // Parse aabb
auto boxarr = modelboxes->list(i); const auto& boxarr = modelboxes[i];
AABB modelbox; AABB modelbox;
modelbox.a = modelbox.a = glm::vec3(
glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2)); boxarr[0].asNumber(), boxarr[1].asNumber(), boxarr[2].asNumber()
modelbox.b = );
glm::vec3(boxarr->num(3), boxarr->num(4), boxarr->num(5)); modelbox.b = glm::vec3(
boxarr[3].asNumber(), boxarr[4].asNumber(), boxarr[5].asNumber()
);
modelbox.b += modelbox.a; modelbox.b += modelbox.a;
def.modelBoxes.push_back(modelbox); def.modelBoxes.push_back(modelbox);
if (boxarr->size() == 7) if (boxarr.size() == 7) {
for (uint j = 6; j < 12; j++) { for (uint j = 6; j < 12; j++) {
def.modelTextures.emplace_back(boxarr->str(6)); def.modelTextures.emplace_back(boxarr[6].asString());
} }
else if (boxarr->size() == 12) } else if (boxarr.size() == 12) {
for (uint j = 6; j < 12; j++) { for (uint j = 6; j < 12; j++) {
def.modelTextures.emplace_back(boxarr->str(j)); def.modelTextures.emplace_back(boxarr[j].asString());
} }
else } else {
for (uint j = 6; j < 12; j++) { for (uint j = 6; j < 12; j++) {
def.modelTextures.emplace_back("notfound"); def.modelTextures.emplace_back("notfound");
} }
}
} }
} }
if (primitives->has("tetragons")) { if (primitives.has("tetragons")) {
auto modeltetragons = primitives->list("tetragons"); const auto& modeltetragons = primitives["tetragons"];
for (uint i = 0; i < modeltetragons->size(); i++) { for (uint i = 0; i < modeltetragons.size(); i++) {
/* Parse tetragon to points */ // Parse tetragon to points
auto tgonobj = modeltetragons->list(i); const auto& tgonobj = modeltetragons[i];
glm::vec3 p1(tgonobj->num(0), tgonobj->num(1), tgonobj->num(2)), glm::vec3 p1(
xw(tgonobj->num(3), tgonobj->num(4), tgonobj->num(5)), tgonobj[0].asNumber(), tgonobj[1].asNumber(), tgonobj[2].asNumber()
yh(tgonobj->num(6), tgonobj->num(7), tgonobj->num(8)); );
glm::vec3 xw(
tgonobj[3].asNumber(), tgonobj[4].asNumber(), tgonobj[5].asNumber()
);
glm::vec3 yh(
tgonobj[6].asNumber(), tgonobj[7].asNumber(), tgonobj[8].asNumber()
);
def.modelExtraPoints.push_back(p1); def.modelExtraPoints.push_back(p1);
def.modelExtraPoints.push_back(p1 + xw); def.modelExtraPoints.push_back(p1 + xw);
def.modelExtraPoints.push_back(p1 + xw + yh); def.modelExtraPoints.push_back(p1 + xw + yh);
def.modelExtraPoints.push_back(p1 + yh); def.modelExtraPoints.push_back(p1 + yh);
def.modelTextures.emplace_back(tgonobj->str(9)); def.modelTextures.emplace_back(tgonobj[9].asString());
} }
} }
} }
@ -302,9 +319,8 @@ void ContentLoader::loadItem(
) { ) {
auto root = files::read_json(file); auto root = files::read_json(file);
if (root->has("parent")) { if (root.has("parent")) {
std::string parentName; const auto& parentName = root["parent"].asString();
root->str("parent", parentName);
auto parentDef = this->builder.items.get(parentName); auto parentDef = this->builder.items.get(parentName);
if (parentDef == nullptr) { if (parentDef == nullptr) {
throw std::runtime_error( throw std::runtime_error(
@ -313,11 +329,10 @@ void ContentLoader::loadItem(
} }
parentDef->cloneTo(def); parentDef->cloneTo(def);
} }
root.at("caption").get(def.caption);
root->str("caption", def.caption);
std::string iconTypeStr = ""; std::string iconTypeStr = "";
root->str("icon-type", iconTypeStr); root.at("icon-type").get(iconTypeStr);
if (iconTypeStr == "none") { if (iconTypeStr == "none") {
def.iconType = item_icon_type::none; def.iconType = item_icon_type::none;
} else if (iconTypeStr == "block") { } else if (iconTypeStr == "block") {
@ -327,16 +342,17 @@ void ContentLoader::loadItem(
} else if (iconTypeStr.length()) { } else if (iconTypeStr.length()) {
logger.error() << name << ": unknown icon type" << iconTypeStr; logger.error() << name << ": unknown icon type" << iconTypeStr;
} }
root->str("icon", def.icon); root.at("icon").get(def.icon);
root->str("placing-block", def.placingBlock); root.at("placing-block").get(def.placingBlock);
root->str("script-name", def.scriptName); root.at("script-name").get(def.scriptName);
root->num("stack-size", def.stackSize); root.at("stack-size").get(def.stackSize);
// item light emission [r, g, b] where r,g,b in range [0..15] // item light emission [r, g, b] where r,g,b in range [0..15]
if (auto emissionarr = root->list("emission")) { if (auto found = root.at("emission")) {
def.emission[0] = emissionarr->num(0); const auto& emissionarr = *found;
def.emission[1] = emissionarr->num(1); def.emission[0] = emissionarr[0].asNumber();
def.emission[2] = emissionarr->num(2); def.emission[1] = emissionarr[1].asNumber();
def.emission[2] = emissionarr[2].asNumber();
} }
} }
@ -345,9 +361,8 @@ void ContentLoader::loadEntity(
) { ) {
auto root = files::read_json(file); auto root = files::read_json(file);
if (root->has("parent")) { if (root.has("parent")) {
std::string parentName; const auto& parentName = root["parent"].asString();
root->str("parent", parentName);
auto parentDef = this->builder.entities.get(parentName); auto parentDef = this->builder.entities.get(parentName);
if (parentDef == nullptr) { if (parentDef == nullptr) {
throw std::runtime_error( throw std::runtime_error(
@ -357,54 +372,57 @@ void ContentLoader::loadEntity(
parentDef->cloneTo(def); parentDef->cloneTo(def);
} }
if (auto componentsarr = root->list("components")) { if (auto found = root.at("components")) {
for (size_t i = 0; i < componentsarr->size(); i++) { for (const auto& elem : *found) {
def.components.emplace_back(componentsarr->str(i)); def.components.emplace_back(elem.asString());
} }
} }
if (auto boxarr = root->list("hitbox")) { if (auto found = root.at("hitbox")) {
def.hitbox = glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2)); const auto& arr = *found;
def.hitbox = glm::vec3(
arr[0].asNumber(), arr[1].asNumber(), arr[2].asNumber()
);
} }
if (auto sensorsarr = root->list("sensors")) { if (auto found = root.at("sensors")) {
for (size_t i = 0; i < sensorsarr->size(); i++) { const auto& arr = *found;
if (auto sensorarr = sensorsarr->list(i)) { for (size_t i = 0; i < arr.size(); i++) {
auto sensorType = sensorarr->str(0); const auto& sensorarr = arr[i];
if (sensorType == "aabb") { const auto& sensorType = sensorarr[0].asString();
def.boxSensors.emplace_back( if (sensorType == "aabb") {
i, def.boxSensors.emplace_back(
AABB { i,
{sensorarr->num(1), AABB {
sensorarr->num(2), {sensorarr[1].asNumber(),
sensorarr->num(3)}, sensorarr[2].asNumber(),
{sensorarr->num(4), sensorarr[3].asNumber()},
sensorarr->num(5), {sensorarr[4].asNumber(),
sensorarr->num(6)} sensorarr[5].asNumber(),
} sensorarr[6].asNumber()}
); }
} else if (sensorType == "radius") { );
def.radialSensors.emplace_back(i, sensorarr->num(1)); } else if (sensorType == "radius") {
} else { def.radialSensors.emplace_back(i, sensorarr[1].asNumber());
logger.error() } else {
<< name << ": sensor #" << i << " - unknown type " logger.error()
<< util::quote(sensorType); << name << ": sensor #" << i << " - unknown type "
} << util::quote(sensorType);
} }
} }
} }
root->flag("save", def.save.enabled); root.at("save").get(def.save.enabled);
root->flag("save-skeleton-pose", def.save.skeleton.pose); root.at("save-skeleton-pose").get(def.save.skeleton.pose);
root->flag("save-skeleton-textures", def.save.skeleton.textures); root.at("save-skeleton-textures").get(def.save.skeleton.textures);
root->flag("save-body-velocity", def.save.body.velocity); root.at("save-body-velocity").get(def.save.body.velocity);
root->flag("save-body-settings", def.save.body.settings); root.at("save-body-settings").get(def.save.body.settings);
std::string bodyTypeName; std::string bodyTypeName;
root->str("body-type", bodyTypeName); root.at("body-type").get(bodyTypeName);
if (auto bodyType = BodyType_from(bodyTypeName)) { if (auto bodyType = BodyType_from(bodyTypeName)) {
def.bodyType = *bodyType; def.bodyType = *bodyType;
} }
root->str("skeleton-name", def.skeletonName); root.at("skeleton-name").get(def.skeletonName);
root->flag("blocking", def.blocking); root.at("blocking").get(def.blocking);
} }
void ContentLoader::loadEntity( void ContentLoader::loadEntity(
@ -458,9 +476,9 @@ void ContentLoader::loadBlockMaterial(
BlockMaterial& def, const fs::path& file BlockMaterial& def, const fs::path& file
) { ) {
auto root = files::read_json(file); auto root = files::read_json(file);
root->str("steps-sound", def.stepsSound); root.at("steps-sound").get(def.stepsSound);
root->str("place-sound", def.placeSound); root.at("place-sound").get(def.placeSound);
root->str("break-sound", def.breakSound); root.at("break-sound").get(def.breakSound);
} }
void ContentLoader::load() { void ContentLoader::load() {
@ -486,7 +504,7 @@ void ContentLoader::load() {
std::string parent; std::string parent;
if (fs::exists(configFile)) { if (fs::exists(configFile)) {
auto root = files::read_json(configFile); auto root = files::read_json(configFile);
if (root->has("parent")) root->str("parent", parent); root.at("parent").get(parent);
} }
return parent; return parent;
}; };
@ -500,9 +518,10 @@ void ContentLoader::load() {
return std::make_pair(full, new_name); return std::make_pair(full, new_name);
}; };
if (auto blocksarr = root->list("blocks")) { if (auto found = root.at("blocks")) {
for (size_t i = 0; i < blocksarr->size(); i++) { const auto& blocksarr = *found;
auto [full, name] = processName(blocksarr->str(i)); for (size_t i = 0; i < blocksarr.size(); i++) {
auto [full, name] = processName(blocksarr[i].asString());
auto parent = getJsonParent("blocks", name); auto parent = getJsonParent("blocks", name);
if (parent.empty() || builder.blocks.get(parent)) { if (parent.empty() || builder.blocks.get(parent)) {
// No dependency or dependency already loaded/exists in another // No dependency or dependency already loaded/exists in another
@ -544,9 +563,10 @@ void ContentLoader::load() {
} }
} }
if (auto itemsarr = root->list("items")) { if (auto found = root.at("items")) {
for (size_t i = 0; i < itemsarr->size(); i++) { const auto& itemsarr = *found;
auto [full, name] = processName(itemsarr->str(i)); for (size_t i = 0; i < itemsarr.size(); i++) {
auto [full, name] = processName(itemsarr[i].asString());
auto parent = getJsonParent("items", name); auto parent = getJsonParent("items", name);
if (parent.empty() || builder.items.get(parent)) { if (parent.empty() || builder.items.get(parent)) {
// No dependency or dependency already loaded/exists in another // No dependency or dependency already loaded/exists in another
@ -588,9 +608,10 @@ void ContentLoader::load() {
} }
} }
if (auto entitiesarr = root->list("entities")) { if (auto found = root.at("entities")) {
for (size_t i = 0; i < entitiesarr->size(); i++) { const auto& entitiesarr = *found;
auto [full, name] = processName(entitiesarr->str(i)); for (size_t i = 0; i < entitiesarr.size(); i++) {
auto [full, name] = processName(entitiesarr[i].asString());
auto parent = getJsonParent("entities", name); auto parent = getJsonParent("entities", name);
if (parent.empty() || builder.entities.get(parent)) { if (parent.empty() || builder.entities.get(parent)) {
// No dependency or dependency already loaded/exists in another // No dependency or dependency already loaded/exists in another
@ -669,11 +690,9 @@ void ContentLoader::load() {
fs::path resourcesFile = folder / fs::u8path("resources.json"); fs::path resourcesFile = folder / fs::u8path("resources.json");
if (fs::exists(resourcesFile)) { if (fs::exists(resourcesFile)) {
auto resRoot = files::read_json(resourcesFile); auto resRoot = files::read_json(resourcesFile);
for (const auto& [key, _] : resRoot->values) { for (const auto& [key, arr] : resRoot.asObject()) {
if (auto resType = ResourceType_from(key)) { if (auto resType = ResourceType_from(key)) {
if (auto arr = resRoot->list(key)) { loadResources(*resType, arr);
loadResources(*resType, arr.get());
}
} else { } else {
logger.warning() << "unknown resource type: " << key; logger.warning() << "unknown resource type: " << key;
} }
@ -681,10 +700,10 @@ void ContentLoader::load() {
} }
} }
void ContentLoader::loadResources(ResourceType type, dynamic::List* list) { void ContentLoader::loadResources(ResourceType type, const dv::value& list) {
for (size_t i = 0; i < list->size(); i++) { for (size_t i = 0; i < list.size(); i++) {
builder.resourceIndices[static_cast<size_t>(type)].add( builder.resourceIndices[static_cast<size_t>(type)].add(
pack->id + ":" + list->str(i), nullptr pack->id + ":" + list[i].asString(), nullptr
); );
} }
} }

View File

@ -5,6 +5,7 @@
#include <string> #include <string>
#include "content_fwd.hpp" #include "content_fwd.hpp"
#include "data/dv.hpp"
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -18,11 +19,6 @@ class ContentBuilder;
class ContentPackRuntime; class ContentPackRuntime;
struct ContentPackStats; struct ContentPackStats;
namespace dynamic {
class Map;
class List;
}
class ContentLoader { class ContentLoader {
const ContentPack* pack; const ContentPack* pack;
ContentPackRuntime* runtime; ContentPackRuntime* runtime;
@ -40,7 +36,7 @@ class ContentLoader {
EntityDef& def, const std::string& full, const std::string& name EntityDef& def, const std::string& full, const std::string& name
); );
static void loadCustomBlockModel(Block& def, dynamic::Map* primitives); static void loadCustomBlockModel(Block& def, const dv::value& primitives);
static void loadBlockMaterial(BlockMaterial& def, const fs::path& file); static void loadBlockMaterial(BlockMaterial& def, const fs::path& file);
void loadBlock( void loadBlock(
Block& def, const std::string& name, const fs::path& file Block& def, const std::string& name, const fs::path& file
@ -51,13 +47,13 @@ class ContentLoader {
void loadEntity( void loadEntity(
EntityDef& def, const std::string& name, const fs::path& file EntityDef& def, const std::string& name, const fs::path& file
); );
void loadResources(ResourceType type, dynamic::List* list); void loadResources(ResourceType type, const dv::value& list);
public: public:
ContentLoader(ContentPack* pack, ContentBuilder& builder); ContentLoader(ContentPack* pack, ContentBuilder& builder);
bool fixPackIndices( bool fixPackIndices(
const fs::path& folder, const fs::path& folder,
dynamic::Map* indicesRoot, dv::value& indicesRoot,
const std::string& contentSection const std::string& contentSection
); );
void fixPackIndices(); void fixPackIndices();

View File

@ -6,7 +6,7 @@
#include "constants.hpp" #include "constants.hpp"
#include "coders/json.hpp" #include "coders/json.hpp"
#include "data/dynamic.hpp" #include "data/dv.hpp"
#include "files/engine_paths.hpp" #include "files/engine_paths.hpp"
#include "files/files.hpp" #include "files/files.hpp"
@ -72,18 +72,18 @@ static void checkContentPackId(const std::string& id, const fs::path& folder) {
ContentPack ContentPack::read(const fs::path& folder) { ContentPack ContentPack::read(const fs::path& folder) {
auto root = files::read_json(folder / fs::path(PACKAGE_FILENAME)); auto root = files::read_json(folder / fs::path(PACKAGE_FILENAME));
ContentPack pack; ContentPack pack;
root->str("id", pack.id); root.at("id").get(pack.id);
root->str("title", pack.title); root.at("title").get(pack.title);
root->str("version", pack.version); root.at("version").get(pack.version);
root->str("creator", pack.creator); root.at("creator").get(pack.creator);
root->str("description", pack.description); root.at("description").get(pack.description);
pack.folder = folder; pack.folder = folder;
auto dependencies = root->list("dependencies"); if (auto found = root.at("dependencies")) {
if (dependencies) { const auto& dependencies = *found;
for (size_t i = 0; i < dependencies->size(); i++) { for (const auto& elem : dependencies) {
pack.dependencies.push_back( pack.dependencies.push_back(
{DependencyLevel::required, dependencies->str(i)} {DependencyLevel::required, elem.asString()}
); );
} }
} }

View File

@ -23,16 +23,12 @@ namespace dv {
} }
value& value::operator[](const key_t& key) { value& value::operator[](const key_t& key) {
if (type == value_type::object) { check_type(type, value_type::object);
return (*val.object)[key]; return (*val.object)[key];
}
throw std::runtime_error("value is not an object");
} }
const value& value::operator[](const key_t& key) const { const value& value::operator[](const key_t& key) const {
if (type == value_type::object) { check_type(type, value_type::object);
return (*val.object)[key]; return (*val.object)[key];
}
throw std::runtime_error("value is not an object");
} }
value& value::operator=(const objects::Bytes& bytes) { value& value::operator=(const objects::Bytes& bytes) {
@ -40,23 +36,17 @@ namespace dv {
} }
value& value::operator[](size_t index) { value& value::operator[](size_t index) {
if (type == value_type::list) { check_type(type, value_type::list);
return (*val.list)[index]; return (*val.list)[index];
}
throw std::runtime_error("value is not a list");
} }
const value& value::operator[](size_t index) const { const value& value::operator[](size_t index) const {
if (type == value_type::list) { check_type(type, value_type::list);
return (*val.list)[index]; return (*val.list)[index];
}
throw std::runtime_error("value is not a list");
} }
void value::add(value v) { void value::add(value v) {
if (type == value_type::list) { check_type(type, value_type::list);
return val.list->push(std::move(v)); return val.list->push_back(std::move(v));
}
throw std::runtime_error("value is not a list");
} }
value& value::object(const key_t& key) { value& value::object(const key_t& key) {
@ -72,54 +62,42 @@ namespace dv {
} }
value& value::object() { value& value::object() {
if (type == value_type::list) { check_type(type, value_type::list);
return val.list->add(std::make_shared<objects::Object>()); val.list->push_back(std::make_shared<objects::Object>());
} return val.list->operator[](val.list->size()-1);
throw std::runtime_error("value is not a list");
} }
value& value::list() { value& value::list() {
if (type == value_type::list) { check_type(type, value_type::list);
return val.list->add(std::make_shared<objects::List>()); val.list->push_back(std::make_shared<objects::List>());
} return val.list->operator[](val.list->size()-1);
throw std::runtime_error("value is not a list");
} }
list_t::iterator value::begin() { list_t::iterator value::begin() {
if (type == value_type::list) { check_type(type, value_type::list);
return val.list->begin(); return val.list->begin();
}
throw std::runtime_error("value is not a list");
} }
list_t::iterator value::end() { list_t::iterator value::end() {
if (type == value_type::list) { check_type(type, value_type::list);
return val.list->end(); return val.list->end();
}
throw std::runtime_error("value is not a list");
} }
list_t::const_iterator value::begin() const { list_t::const_iterator value::begin() const {
if (type == value_type::list) { check_type(type, value_type::list);
const auto& constlist = *val.list; const auto& constlist = *val.list;
return constlist.begin(); return constlist.begin();
}
throw std::runtime_error("value is not a list");
} }
list_t::const_iterator value::end() const { list_t::const_iterator value::end() const {
if (type == value_type::list) { check_type(type, value_type::list);
const auto& constlist = *val.list; const auto& constlist = *val.list;
return constlist.end(); return constlist.end();
}
throw std::runtime_error("value is not a list");
} }
const std::string& value::asString() const { const std::string& value::asString() const {
if (type == value_type::string) { check_type(type, value_type::string);
return *val.string; return *val.string;
}
throw std::runtime_error("type error");
} }
integer_t value::asInteger() const { integer_t value::asInteger() const {
@ -128,7 +106,8 @@ namespace dv {
} else if (type == value_type::number) { } else if (type == value_type::number) {
return static_cast<integer_t>(val.number); return static_cast<integer_t>(val.number);
} }
throw std::runtime_error("type error"); throw_type_error(type, value_type::integer);
return 0; // unreachable
} }
number_t value::asNumber() const { number_t value::asNumber() const {
@ -137,7 +116,8 @@ namespace dv {
} else if (type == value_type::integer) { } else if (type == value_type::integer) {
return static_cast<number_t>(val.integer); return static_cast<number_t>(val.integer);
} }
throw std::runtime_error("type error"); throw_type_error(type, value_type::integer);
return 0; // unreachable
} }
boolean_t value::asBoolean() const { boolean_t value::asBoolean() const {
@ -146,31 +126,26 @@ namespace dv {
} else if (type == value_type::integer) { } else if (type == value_type::integer) {
return val.integer != 0; return val.integer != 0;
} }
throw std::runtime_error("type error"); throw_type_error(type, value_type::boolean);
return false; // unreachable
} }
objects::Bytes& value::asBytes() { objects::Bytes& value::asBytes() {
if (type == value_type::bytes) { check_type(type, value_type::bytes);
return *val.bytes; return *val.bytes;
}
throw std::runtime_error("type error");
} }
const objects::Bytes& value::asBytes() const { const objects::Bytes& value::asBytes() const {
if (type == value_type::bytes) { check_type(type, value_type::bytes);
return *val.bytes; return *val.bytes;
}
throw std::runtime_error("type error");
} }
const objects::Object& value::asObject() const { const objects::Object& value::asObject() const {
if (type == value_type::object) { check_type(type, value_type::object);
return *val.object; return *val.object;
}
throw std::runtime_error("type error");
} }
const size_t value::size() const { size_t value::size() const {
switch (type) { switch (type) {
case value_type::list: case value_type::list:
return val.list->size(); return val.list->size();
@ -179,8 +154,30 @@ namespace dv {
case value_type::string: case value_type::string:
return val.string->size(); return val.string->size();
default: default:
throw std::runtime_error("type error"); return 0;
} }
} }
bool value::has(const key_t& k) const {
if (type == value_type::object) {
return val.object->find(k) != val.object->end();
}
return false;
}
void value::erase(const key_t& key) {
check_type(type, value_type::object);
val.object->erase(key);
}
void value::erase(size_t index) {
check_type(type, value_type::list);
val.list->erase(val.list->begin() + index);
}
} }
#include "coders/json.hpp"
std::ostream& operator<<(std::ostream& stream, const dv::value& value) {
return stream << json::stringify(value, false);
}

View File

@ -6,6 +6,7 @@
#include <vector> #include <vector>
#include <cstring> #include <cstring>
#include <stdexcept> #include <stdexcept>
#include <functional>
#include <unordered_map> #include <unordered_map>
namespace util { namespace util {
@ -30,10 +31,18 @@ namespace dv {
string string
}; };
namespace objects { inline const std::string& type_name(value_type type) {
class Object; static std::string type_names[] = {
class List; "none",
using Bytes = util::Buffer<byte_t>; "number",
"boolean",
"integer",
"object",
"list",
"bytes",
"string"
};
return type_names[static_cast<int>(type)];
} }
class value; class value;
@ -45,6 +54,58 @@ namespace dv {
using reference = value&; using reference = value&;
using const_reference = const value&; using const_reference = const value&;
namespace objects {
using Object = std::unordered_map<key_t, value>;
using List = std::vector<value>;
using Bytes = util::Buffer<byte_t>;
}
/// @brief nullable value reference returned by value.at(...)
struct elementreference {
value* ptr;
elementreference(value* ptr) : ptr(ptr) {}
inline operator bool() const {
return ptr != nullptr;
}
inline value& operator*() {
return *ptr;
}
inline const value& operator*() const {
return *ptr;
}
bool get(std::string& dst) const;
bool get(bool& dst) const;
bool get(int8_t& dst) const;
bool get(int16_t& dst) const;
bool get(int32_t& dst) const;
bool get(int64_t& dst) const;
bool get(uint8_t& dst) const;
bool get(uint16_t& dst) const;
bool get(uint32_t& dst) const;
bool get(uint64_t& dst) const;
bool get(float& dst) const;
bool get(double& dst) const;
};
inline void throw_type_error(value_type got, value_type expected) {
// place breakpoint here to find cause
throw std::runtime_error(
"type error: expected " + type_name(expected) + ", got " +
type_name(got)
);
}
inline void check_type(value_type got, value_type expected) {
if (got != expected) {
throw_type_error(got, expected);
}
}
class value { class value {
value_type type = value_type::none; value_type type = value_type::none;
union value_u { union value_u {
@ -149,6 +210,10 @@ namespace dv {
} }
} }
inline value& operator=(std::nullptr_t) {
return setNone();
}
inline value& operator=(int8_t v) { inline value& operator=(int8_t v) {
return setInteger(v); return setInteger(v);
} }
@ -302,6 +367,10 @@ namespace dv {
return add(value(v)); return add(value(v));
} }
void erase(const key_t& key);
void erase(size_t index);
value& operator[](const key_t& key); value& operator[](const key_t& key);
const value& operator[](const key_t& key) const; const value& operator[](const key_t& key) const;
@ -310,6 +379,14 @@ namespace dv {
const value& operator[](size_t index) const; const value& operator[](size_t index) const;
bool operator!=(std::nullptr_t) const noexcept {
return type != value_type::none;
}
bool operator==(std::nullptr_t) const noexcept {
return type == value_type::none;
}
value& object(const key_t& key); value& object(const key_t& key);
value& list(const key_t& key); value& list(const key_t& key);
@ -342,93 +419,109 @@ namespace dv {
return type; return type;
} }
const size_t size() const; std::string asString(std::string def) const {
if (type != value_type::string) {
return def;
}
return *val.string;
}
const size_t length() const { std::string asString(const char* s) const {
return asString(std::string(s));
}
integer_t asBoolean(boolean_t def) const {
switch (type) {
case value_type::boolean:
return val.boolean;
default:
return def;
}
}
integer_t asInteger(integer_t def) const {
switch (type) {
case value_type::integer:
return val.integer;
case value_type::number:
return static_cast<integer_t>(val.number);
default:
return def;
}
}
integer_t asNumber(integer_t def) const {
switch (type) {
case value_type::integer:
return static_cast<number_t>(val.integer);
case value_type::number:
return val.number;
default:
return def;
}
}
elementreference at(const key_t& k) const {
check_type(type, value_type::object);
const auto& found = val.object->find(k);
if (found == val.object->end()) {
return elementreference(nullptr);
}
return elementreference(&found->second);
}
elementreference at(size_t index) {
check_type(type, value_type::list);
return elementreference(&val.list->at(index));
}
const elementreference at(size_t index) const {
check_type(type, value_type::list);
return elementreference(&val.list->at(index));
}
bool has(const key_t& k) const;
size_t size() const;
size_t length() const {
return size(); return size();
} }
inline bool empty() const { inline bool empty() const {
return size() == 0; return size() == 0;
} }
inline bool isString() const {
return type == value_type::string;
}
inline bool isObject() const {
return type == value_type::object;
}
inline bool isList() const {
return type == value_type::list;
}
inline bool isInteger() const {
return type == value_type::integer;
}
inline bool isNumber() const {
return type == value_type::number;
}
}; };
inline value none = value(); inline value none = value();
}
namespace dv::objects { inline bool is_numeric(const value& val) {
class Object { return val.isInteger() && val.isNumber();
map_t map; }
public:
Object() = default;
Object(std::initializer_list<pair> pairs) : map(pairs) {}
Object(const Object&) = delete;
~Object() = default;
reference operator[](const key_t& key) { using to_string_func = std::function<std::string(const value&)>;
return map[key];
}
const_reference operator[](const key_t& key) const {
return map.at(key);
}
map_t::const_iterator begin() const {
return map.begin();
}
map_t::const_iterator end() const {
return map.end();
}
const size_t size() const {
return map.size();
}
};
class List {
list_t list;
public:
List() = default;
List(std::initializer_list<value> values) : list(values) {}
List(const List&) = delete;
~List() = default;
reference operator[](std::size_t index) {
return list.at(index);
}
const_reference operator[](std::size_t index) const {
return list.at(index);
}
void push(value v) {
list.push_back(std::move(v));
}
reference add(value v) {
list.push_back(std::move(v));
return list[list.size()-1];
}
auto begin() {
return list.begin();
}
auto end() {
return list.end();
}
list_t::const_iterator begin() const {
return list.begin();
}
list_t::const_iterator end() const {
return list.end();
}
const size_t size() const {
return list.size();
}
};
} }
namespace dv { namespace dv {
inline const std::string& type_name(const value& value) {
return type_name(value.getType());
}
inline value object() { inline value object() {
return std::make_shared<objects::Object>(); return std::make_shared<objects::Object>();
} }
@ -440,4 +533,67 @@ namespace dv {
inline value list(std::initializer_list<value> values) { inline value list(std::initializer_list<value> values) {
return std::make_shared<objects::List>(values); return std::make_shared<objects::List>(values);
} }
template<typename T> inline bool get_to_int(value* ptr, T& dst) {
if (ptr) {
dst = ptr->asInteger();
return true;
}
return false;
}
template<typename T> inline bool get_to_num(value* ptr, T& dst) {
if (ptr) {
dst = ptr->asNumber();
return true;
}
return false;
}
inline bool elementreference::get(std::string& dst) const {
if (ptr) {
dst = ptr->asString();
return true;
}
return false;
}
inline bool elementreference::get(bool& dst) const {
if (ptr) {
dst = ptr->asBoolean();
return true;
}
return false;
}
inline bool elementreference::get(int8_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(int16_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(int32_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(int64_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(uint8_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(uint16_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(uint32_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(uint64_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(float& dst) const {
return get_to_num(ptr, dst);
}
inline bool elementreference::get(double& dst) const {
return get_to_num(ptr, dst);
}
} }
std::ostream& operator<<(std::ostream& stream, const dv::value& value);

74
src/data/dv_util.hpp Normal file
View File

@ -0,0 +1,74 @@
#pragma once
#include "dv.hpp"
#include <glm/glm.hpp>
namespace dv {
template <int n>
inline dv::value to_value(glm::vec<n, float> vec) {
auto list = dv::list();
for (size_t i = 0; i < n; i++) {
list.add(vec[i]);
}
return list;
}
template <int n, int m>
inline dv::value to_value(glm::mat<n, m, float> mat) {
auto list = dv::list();
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < m; j++) {
list.add(mat[i][j]);
}
}
return list;
}
template <int n>
void get_vec(const dv::value& list, glm::vec<n, float>& vec) {
for (size_t i = 0; i < n; i++) {
vec[i] = list[i].asNumber();
}
}
template <int n>
void get_vec(const dv::value& map, const std::string& key, glm::vec<n, float>& vec) {
if (!map.has(key)) {
return;
}
auto& list = map[key];
for (size_t i = 0; i < n; i++) {
vec[i] = list[i].asNumber();
}
}
template <int n, int m>
void get_mat(
const dv::value& list,
glm::mat<n, m, float>& mat
) {
for (size_t y = 0; y < n; y++) {
for (size_t x = 0; x < m; x++) {
mat[y][x] = list[y * m + x].asNumber();
}
}
}
template <int n, int m>
void get_mat(
const dv::value& map,
const std::string& key,
glm::mat<n, m, float>& mat
) {
if (!map.has(key)) {
return;
}
auto& list = map[key];
for (size_t y = 0; y < n; y++) {
for (size_t x = 0; x < m; x++) {
mat[y][x] = list[y * m + x].asNumber();
}
}
}
}

View File

@ -1,345 +0,0 @@
#include "dynamic.hpp"
#include "coders/json.hpp"
using namespace dynamic;
std::ostream& operator<<(std::ostream& stream, const dynamic::Value& value) {
stream << json::stringify(value, false, " ");
return stream;
}
std::ostream& operator<<(std::ostream& stream, const dynamic::Map& value) {
stream << json::stringify(&value, false, " ");
return stream;
}
std::ostream& operator<<(std::ostream& stream, const dynamic::Map_sptr& value) {
stream << json::stringify(value, false, " ");
return stream;
}
std::ostream& operator<<(std::ostream& stream, const dynamic::List& value) {
stream << json::stringify(&value, false, " ");
return stream;
}
std::ostream& operator<<(
std::ostream& stream, const dynamic::List_sptr& value
) {
stream << json::stringify(value, false, " ");
return stream;
}
std::string List::str(size_t index) const {
const auto& value = values[index];
switch (static_cast<Type>(value.index())) {
case Type::string:
return std::get<std::string>(value);
case Type::boolean:
return std::get<bool>(value) ? "true" : "false";
case Type::number:
return std::to_string(std::get<double>(value));
case Type::integer:
return std::to_string(std::get<int64_t>(value));
default:
throw std::runtime_error("type error");
}
}
number_t List::num(size_t index) const {
const auto& value = values[index];
switch (static_cast<Type>(value.index())) {
case Type::number:
return std::get<number_t>(value);
case Type::integer:
return std::get<integer_t>(value);
case Type::string:
return std::stoll(std::get<std::string>(value));
case Type::boolean:
return std::get<bool>(value);
default:
throw std::runtime_error("type error");
}
}
integer_t List::integer(size_t index) const {
const auto& value = values[index];
switch (static_cast<Type>(value.index())) {
case Type::number:
return std::get<number_t>(value);
case Type::integer:
return std::get<integer_t>(value);
case Type::string:
return std::stoll(std::get<std::string>(value));
case Type::boolean:
return std::get<bool>(value);
default:
throw std::runtime_error("type error");
}
}
const Map_sptr& List::map(size_t index) const {
if (auto* val = std::get_if<Map_sptr>(&values[index])) {
return *val;
} else {
throw std::runtime_error("type error");
}
}
List* List::list(size_t index) const {
if (auto* val = std::get_if<List_sptr>(&values[index])) {
return val->get();
} else {
throw std::runtime_error("type error");
}
}
bool List::flag(size_t index) const {
const auto& value = values[index];
switch (static_cast<Type>(value.index())) {
case Type::integer:
return std::get<integer_t>(value);
case Type::boolean:
return std::get<bool>(value);
default:
throw std::runtime_error("type error");
}
}
Value* List::getValueWriteable(size_t index) {
return &values.at(index);
}
List& List::put(const Value& value) {
values.emplace_back(value);
return *this;
}
List& List::putList() {
auto arr = create_list();
put(arr);
return *arr;
}
Map& List::putMap() {
auto map = create_map();
put(map);
return *map;
}
ByteBuffer& List::putBytes(size_t size) {
auto bytes = create_bytes(size);
put(bytes);
return *bytes;
}
void List::remove(size_t index) {
values.erase(values.begin() + index);
}
void Map::str(const std::string& key, std::string& dst) const {
dst = get(key, dst);
}
std::string Map::get(const std::string& key, const std::string& def) const {
auto found = values.find(key);
if (found == values.end()) return def;
auto& value = found->second;
switch (static_cast<Type>(value.index())) {
case Type::string:
return std::get<std::string>(value);
case Type::boolean:
return std::get<bool>(value) ? "true" : "false";
case Type::number:
return std::to_string(std::get<number_t>(value));
case Type::integer:
return std::to_string(std::get<integer_t>(value));
default:
throw std::runtime_error("type error");
}
}
number_t Map::get(const std::string& key, double def) const {
auto found = values.find(key);
if (found == values.end()) return def;
auto& value = found->second;
switch (static_cast<Type>(value.index())) {
case Type::number:
return std::get<number_t>(value);
case Type::integer:
return std::get<integer_t>(value);
case Type::string:
return std::stoull(std::get<std::string>(value));
case Type::boolean:
return std::get<bool>(value);
default:
throw std::runtime_error("type error");
}
}
integer_t Map::get(const std::string& key, integer_t def) const {
auto found = values.find(key);
if (found == values.end()) return def;
auto& value = found->second;
switch (static_cast<Type>(value.index())) {
case Type::number:
return std::get<number_t>(value);
case Type::integer:
return std::get<integer_t>(value);
case Type::string:
return std::stoull(std::get<std::string>(value));
case Type::boolean:
return std::get<bool>(value);
default:
throw std::runtime_error("type error");
}
}
bool Map::get(const std::string& key, bool def) const {
auto found = values.find(key);
if (found == values.end()) return def;
auto& value = found->second;
switch (static_cast<Type>(value.index())) {
case Type::integer:
return std::get<integer_t>(value);
case Type::boolean:
return std::get<bool>(value);
default:
throw std::runtime_error("type error");
}
}
void Map::num(const std::string& key, double& dst) const {
dst = get(key, dst);
}
void Map::num(const std::string& key, float& dst) const {
dst = get(key, static_cast<number_t>(dst));
}
void Map::num(const std::string& key, ubyte& dst) const {
dst = get(key, static_cast<integer_t>(dst));
}
void Map::num(const std::string& key, int& dst) const {
dst = get(key, static_cast<integer_t>(dst));
}
void Map::num(const std::string& key, int64_t& dst) const {
dst = get(key, dst);
}
void Map::num(const std::string& key, uint64_t& dst) const {
dst = get(key, static_cast<integer_t>(dst));
}
void Map::num(const std::string& key, uint& dst) const {
dst = get(key, static_cast<integer_t>(dst));
}
Map_sptr Map::map(const std::string& key) const {
auto found = values.find(key);
if (found != values.end()) {
if (auto* val = std::get_if<Map_sptr>(&found->second)) {
return *val;
}
}
return nullptr;
}
List_sptr Map::list(const std::string& key) const {
auto found = values.find(key);
if (found != values.end()) return std::get<List_sptr>(found->second);
return nullptr;
}
ByteBuffer_sptr Map::bytes(const std::string& key) const {
auto found = values.find(key);
if (found != values.end()) return std::get<ByteBuffer_sptr>(found->second);
return nullptr;
}
void Map::flag(const std::string& key, bool& dst) const {
dst = get(key, dst);
}
Map& Map::put(const std::string& key, const Value& value) {
values[key] = value;
return *this;
}
void Map::remove(const std::string& key) {
values.erase(key);
}
List& Map::putList(const std::string& key) {
auto arr = create_list();
put(key, arr);
return *arr;
}
Map& Map::putMap(const std::string& key) {
auto obj = create_map();
put(key, obj);
return *obj;
}
ByteBuffer& Map::putBytes(const std::string& key, size_t size) {
auto bytes = create_bytes(size);
put(key, bytes);
return *bytes;
}
bool Map::has(const std::string& key) const {
return values.find(key) != values.end();
}
size_t Map::size() const {
return values.size();
}
static const std::string TYPE_NAMES[] {
"none",
"map",
"list",
"string",
"number",
"bool",
"integer",
};
const std::string& dynamic::type_name(const Value& value) {
return TYPE_NAMES[value.index()];
}
List_sptr dynamic::create_list(std::initializer_list<Value> values) {
return std::make_shared<List>(values);
}
Map_sptr dynamic::create_map(
std::initializer_list<std::pair<const std::string, Value>> entries
) {
return std::make_shared<Map>(entries);
}
ByteBuffer_sptr dynamic::create_bytes(size_t size) {
return std::make_shared<ByteBuffer>(size);
}
number_t dynamic::get_number(const Value& value) {
if (auto num = std::get_if<number_t>(&value)) {
return *num;
} else if (auto num = std::get_if<integer_t>(&value)) {
return *num;
}
throw std::runtime_error("cannot cast " + type_name(value) + " to number");
}
integer_t dynamic::get_integer(const Value& value) {
if (auto num = std::get_if<integer_t>(&value)) {
return *num;
}
throw std::runtime_error("cannot cast " + type_name(value) + " to integer");
}

View File

@ -1,190 +0,0 @@
#pragma once
#include <cmath>
#include <memory>
#include <ostream>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>
#include "dynamic_fwd.hpp"
namespace dynamic {
enum class Type {
none = 0,
map,
list,
bytes,
string,
number,
boolean,
integer
};
const std::string& type_name(const Value& value);
List_sptr create_list(std::initializer_list<Value> values = {});
Map_sptr create_map(
std::initializer_list<std::pair<const std::string, Value>> entries = {}
);
ByteBuffer_sptr create_bytes(size_t size);
number_t get_number(const Value& value);
integer_t get_integer(const Value& value);
inline bool is_numeric(const Value& value) {
return std::holds_alternative<number_t>(value) ||
std::holds_alternative<integer_t>(value);
}
inline number_t as_number(const Value& value) {
if (auto num = std::get_if<number_t>(&value)) {
return *num;
} else if (auto num = std::get_if<integer_t>(&value)) {
return *num;
}
return NAN;
}
class List {
public:
std::vector<Value> values;
List() = default;
List(std::vector<Value> values) : values(std::move(values)) {
}
std::string str(size_t index) const;
number_t num(size_t index) const;
integer_t integer(size_t index) const;
const Map_sptr& map(size_t index) const;
List* list(size_t index) const;
bool flag(size_t index) const;
inline size_t size() const {
return values.size();
}
inline Value& get(size_t i) {
return values.at(i);
}
List& put(std::unique_ptr<Map> value) {
return put(Map_sptr(std::move(value)));
}
List& put(std::unique_ptr<List> value) {
return put(List_sptr(std::move(value)));
}
List& put(std::unique_ptr<ByteBuffer> value) {
return put(ByteBuffer_sptr(std::move(value)));
}
List& put(const Value& value);
Value* getValueWriteable(size_t index);
List& putList();
Map& putMap();
ByteBuffer& putBytes(size_t size);
void remove(size_t index);
};
class Map {
public:
std::unordered_map<std::string, Value> values;
Map() = default;
Map(std::unordered_map<std::string, Value> values)
: values(std::move(values)) {};
template <typename T>
T get(const std::string& key) const {
if (!has(key)) {
throw std::runtime_error("missing key '" + key + "'");
}
return get(key, T());
}
std::string get(const std::string& key, const std::string& def) const;
number_t get(const std::string& key, double def) const;
integer_t get(const std::string& key, integer_t def) const;
bool get(const std::string& key, bool def) const;
int get(const std::string& key, int def) const {
return get(key, static_cast<integer_t>(def));
}
uint get(const std::string& key, uint def) const {
return get(key, static_cast<integer_t>(def));
}
uint64_t get(const std::string& key, uint64_t def) const {
return get(key, static_cast<integer_t>(def));
}
void str(const std::string& key, std::string& dst) const;
void num(const std::string& key, int& dst) const;
void num(const std::string& key, float& dst) const;
void num(const std::string& key, uint& dst) const;
void num(const std::string& key, int64_t& dst) const;
void num(const std::string& key, uint64_t& dst) const;
void num(const std::string& key, ubyte& dst) const;
void num(const std::string& key, double& dst) const;
Map_sptr map(const std::string& key) const;
List_sptr list(const std::string& key) const;
ByteBuffer_sptr bytes(const std::string& key) const;
void flag(const std::string& key, bool& dst) const;
Map& put(std::string key, std::unique_ptr<Map> value) {
return put(key, Map_sptr(value.release()));
}
Map& put(std::string key, std::unique_ptr<List> value) {
return put(key, List_sptr(value.release()));
}
Map& put(std::string key, int value) {
return put(key, Value(static_cast<integer_t>(value)));
}
Map& put(std::string key, unsigned int value) {
return put(key, Value(static_cast<integer_t>(value)));
}
Map& put(std::string key, int64_t value) {
return put(key, Value(static_cast<integer_t>(value)));
}
Map& put(std::string key, uint64_t value) {
return put(key, Value(static_cast<integer_t>(value)));
}
Map& put(std::string key, float value) {
return put(key, Value(static_cast<number_t>(value)));
}
Map& put(std::string key, double value) {
return put(key, Value(static_cast<number_t>(value)));
}
Map& put(std::string key, bool value) {
return put(key, Value(static_cast<bool>(value)));
}
Map& put(const std::string& key, const ByteBuffer* bytes) {
return put(key, std::make_unique<ByteBuffer>(
bytes->data(), bytes->size()));
}
Map& put(std::string key, const ubyte* bytes, size_t size) {
return put(key, std::make_unique<ByteBuffer>(bytes, size));
}
Map& put(std::string key, const char* value) {
return put(key, Value(value));
}
Map& put(const std::string& key, const Value& value);
void remove(const std::string& key);
List& putList(const std::string& key);
Map& putMap(const std::string& key);
ByteBuffer& putBytes(const std::string& key, size_t size);
bool has(const std::string& key) const;
size_t size() const;
};
}
std::ostream& operator<<(std::ostream& stream, const dynamic::Value& value);
std::ostream& operator<<(std::ostream& stream, const dynamic::Map& value);
std::ostream& operator<<(std::ostream& stream, const dynamic::Map_sptr& value);
std::ostream& operator<<(std::ostream& stream, const dynamic::List& value);
std::ostream& operator<<(std::ostream& stream, const dynamic::List_sptr& value);

View File

@ -1,35 +0,0 @@
#pragma once
#include <functional>
#include <memory>
#include <string>
#include <variant>
#include "typedefs.hpp"
#include "util/Buffer.hpp"
namespace dynamic {
class Map;
class List;
using ByteBuffer = util::Buffer<ubyte>;
using Map_sptr = std::shared_ptr<Map>;
using List_sptr = std::shared_ptr<List>;
using ByteBuffer_sptr = std::shared_ptr<ByteBuffer>;
struct none {};
inline constexpr none NONE = {};
using Value = std::variant<
none,
Map_sptr,
List_sptr,
ByteBuffer_sptr,
std::string,
number_t,
bool,
integer_t>;
using to_string_func = std::function<std::string(const Value&)>;
}

View File

@ -1,79 +0,0 @@
#pragma once
#include <glm/glm.hpp>
#include "dynamic.hpp"
namespace dynamic {
template <int n>
inline dynamic::List_sptr to_value(glm::vec<n, float> vec) {
auto list = dynamic::create_list();
for (size_t i = 0; i < n; i++) {
list->put(vec[i]);
}
return list;
}
template <int n, int m>
inline dynamic::List_sptr to_value(glm::mat<n, m, float> mat) {
auto list = dynamic::create_list();
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < m; j++) {
list->put(mat[i][j]);
}
}
return list;
}
template <int n>
void get_vec(
const dynamic::Map_sptr& root,
const std::string& name,
glm::vec<n, float>& vec
) {
if (const auto& list = root->list(name)) {
for (size_t i = 0; i < n; i++) {
vec[i] = list->num(i);
}
}
}
template <int n>
void get_vec(
const dynamic::List_sptr& root, size_t index, glm::vec<n, float>& vec
) {
if (const auto& list = root->list(index)) {
for (size_t i = 0; i < n; i++) {
vec[i] = list->num(i);
}
}
}
template <int n, int m>
void get_mat(
const dynamic::Map_sptr& root,
const std::string& name,
glm::mat<n, m, float>& mat
) {
if (const auto& list = root->list(name)) {
for (size_t y = 0; y < n; y++) {
for (size_t x = 0; x < m; x++) {
mat[y][x] = list->num(y * m + x);
}
}
}
}
template <int n, int m>
void get_mat(
const dynamic::List_sptr& root, size_t index, glm::mat<n, m, float>& mat
) {
if (const auto& list = root->list(index)) {
for (size_t y = 0; y < n; y++) {
for (size_t x = 0; x < m; x++) {
mat[y][x] = list->num(y * m + x);
}
}
}
}
}

View File

@ -6,7 +6,6 @@
#include <utility> #include <utility>
#include "content/ContentLUT.hpp" #include "content/ContentLUT.hpp"
#include "data/dynamic.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "files/files.hpp" #include "files/files.hpp"
#include "objects/Player.hpp" #include "objects/Player.hpp"
@ -108,8 +107,8 @@ void WorldConverter::convertRegion(const fs::path& file) const {
void WorldConverter::convertPlayer(const fs::path& file) const { void WorldConverter::convertPlayer(const fs::path& file) const {
logger.info() << "converting player " << file.u8string(); logger.info() << "converting player " << file.u8string();
auto map = files::read_json(file); auto map = files::read_json(file);
Player::convert(map.get(), lut.get()); Player::convert(map, lut.get());
files::write_json(file, map.get()); files::write_json(file, map);
} }
void WorldConverter::convert(const convert_task& task) const { void WorldConverter::convert(const convert_task& task) const {

View File

@ -13,7 +13,6 @@
#include "constants.hpp" #include "constants.hpp"
#include "content/Content.hpp" #include "content/Content.hpp"
#include "core_defs.hpp" #include "core_defs.hpp"
#include "data/dynamic.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "items/Inventory.hpp" #include "items/Inventory.hpp"
#include "items/ItemDef.hpp" #include "items/ItemDef.hpp"
@ -101,23 +100,23 @@ void WorldFiles::writePacks(const std::vector<ContentPack>& packs) {
template <class T> template <class T>
static void write_indices( static void write_indices(
const ContentUnitIndices<T>& indices, dynamic::List& list const ContentUnitIndices<T>& indices, dv::value& list
) { ) {
for (auto unit : indices.getIterable()) { for (auto unit : indices.getIterable()) {
list.put(unit->name); list.add(unit->name);
} }
} }
void WorldFiles::writeIndices(const ContentIndices* indices) { void WorldFiles::writeIndices(const ContentIndices* indices) {
dynamic::Map root; dv::value root = dv::object();
write_indices(indices->blocks, root.putList("blocks")); write_indices(indices->blocks, root.list("blocks"));
write_indices(indices->items, root.putList("items")); write_indices(indices->items, root.list("items"));
write_indices(indices->entities, root.putList("entities")); write_indices(indices->entities, root.list("entities"));
files::write_json(getIndicesFile(), &root); files::write_json(getIndicesFile(), root);
} }
void WorldFiles::writeWorldInfo(const WorldInfo& info) { void WorldFiles::writeWorldInfo(const WorldInfo& info) {
files::write_json(getWorldFile(), info.serialize().get()); files::write_json(getWorldFile(), info.serialize());
} }
std::optional<WorldInfo> WorldFiles::readWorldInfo() { std::optional<WorldInfo> WorldFiles::readWorldInfo() {
@ -128,23 +127,22 @@ std::optional<WorldInfo> WorldFiles::readWorldInfo() {
} }
auto root = files::read_json(file); auto root = files::read_json(file);
WorldInfo info {}; WorldInfo info {};
info.deserialize(root.get()); info.deserialize(root);
return info; return info;
} }
static void read_resources_data( static void read_resources_data(
const Content* content, const dynamic::List_sptr& list, ResourceType type const Content* content, const dv::value& list, ResourceType type
) { ) {
const auto& indices = content->getIndices(type); const auto& indices = content->getIndices(type);
for (size_t i = 0; i < list->size(); i++) { for (size_t i = 0; i < list.size(); i++) {
auto map = list->map(i); auto& map = list[i];
std::string name; const auto& name = map["name"].asString();
map->str("name", name);
size_t index = indices.indexOf(name); size_t index = indices.indexOf(name);
if (index == ResourceIndices::MISSING) { if (index == ResourceIndices::MISSING) {
logger.warning() << "discard " << name; logger.warning() << "discard " << name;
} else { } else {
indices.saveData(index, map->map("saved")); indices.saveData(index, map["saved"]);
} }
} }
} }
@ -156,11 +154,9 @@ bool WorldFiles::readResourcesData(const Content* content) {
return false; return false;
} }
auto root = files::read_json(file); auto root = files::read_json(file);
for (const auto& [key, _] : root->values) { for (const auto& [key, arr] : root.asObject()) {
if (auto resType = ResourceType_from(key)) { if (auto resType = ResourceType_from(key)) {
if (auto arr = root->list(key)) { read_resources_data(content, arr, *resType);
read_resources_data(content, arr, *resType);
}
} else { } else {
logger.warning() << "unknown resource type: " << key; logger.warning() << "unknown resource type: " << key;
} }
@ -168,31 +164,29 @@ bool WorldFiles::readResourcesData(const Content* content) {
return true; return true;
} }
static void erase_pack_indices(dynamic::Map* root, const std::string& id) { static void erase_pack_indices(dv::value& root, const std::string& id) {
auto prefix = id + ":"; auto prefix = id + ":";
auto blocks = root->list("blocks"); auto& blocks = root["blocks"];
for (uint i = 0; i < blocks->size(); i++) { for (uint i = 0; i < blocks.size(); i++) {
auto name = blocks->str(i); auto name = blocks[i].asString();
if (name.find(prefix) != 0) continue; if (name.find(prefix) != 0) continue;
auto value = blocks->getValueWriteable(i); blocks[i] = CORE_AIR;
*value = CORE_AIR;
} }
auto items = root->list("items"); auto& items = root["items"];
for (uint i = 0; i < items->size(); i++) { for (uint i = 0; i < items.size(); i++) {
auto name = items->str(i); auto& name = items[i].asString();
if (name.find(prefix) != 0) continue; if (name.find(prefix) != 0) continue;
auto value = items->getValueWriteable(i); items[i] = CORE_EMPTY;
*value = CORE_EMPTY;
} }
} }
void WorldFiles::removeIndices(const std::vector<std::string>& packs) { void WorldFiles::removeIndices(const std::vector<std::string>& packs) {
auto root = files::read_json(getIndicesFile()); auto root = files::read_json(getIndicesFile());
for (const auto& id : packs) { for (const auto& id : packs) {
erase_pack_indices(root.get(), id); erase_pack_indices(root, id);
} }
files::write_json(getIndicesFile(), root.get()); files::write_json(getIndicesFile(), root);
} }
fs::path WorldFiles::getFolder() const { fs::path WorldFiles::getFolder() const {

View File

@ -6,10 +6,10 @@
#include "coders/byte_utils.hpp" #include "coders/byte_utils.hpp"
#include "coders/rle.hpp" #include "coders/rle.hpp"
#include "data/dynamic.hpp"
#include "items/Inventory.hpp" #include "items/Inventory.hpp"
#include "maths/voxmaths.hpp" #include "maths/voxmaths.hpp"
#include "util/data_io.hpp" #include "util/data_io.hpp"
#include "coders/binary_json.hpp"
#define REGION_FORMAT_MAGIC ".VOXREG" #define REGION_FORMAT_MAGIC ".VOXREG"
@ -364,7 +364,7 @@ static std::unique_ptr<ubyte[]> write_inventories(
for (auto& entry : inventories) { for (auto& entry : inventories) {
builder.putInt32(entry.first); builder.putInt32(entry.first);
auto map = entry.second->serialize(); auto map = entry.second->serialize();
auto bytes = json::to_binary(map.get(), true); auto bytes = json::to_binary(map, true);
builder.putInt32(bytes.size()); builder.putInt32(bytes.size());
builder.put(bytes.data(), bytes.size()); builder.put(bytes.data(), bytes.size());
} }
@ -467,21 +467,21 @@ chunk_inventories_map WorldRegions::fetchInventories(int x, int z) {
auto map = json::from_binary(reader.pointer(), size); auto map = json::from_binary(reader.pointer(), size);
reader.skip(size); reader.skip(size);
auto inv = std::make_shared<Inventory>(0, 0); auto inv = std::make_shared<Inventory>(0, 0);
inv->deserialize(map.get()); inv->deserialize(map);
meta[index] = inv; meta[index] = inv;
} }
return meta; return meta;
} }
dynamic::Map_sptr WorldRegions::fetchEntities(int x, int z) { dv::value WorldRegions::fetchEntities(int x, int z) {
uint32_t bytesSize; uint32_t bytesSize;
const ubyte* data = getData(x, z, REGION_LAYER_ENTITIES, bytesSize); const ubyte* data = getData(x, z, REGION_LAYER_ENTITIES, bytesSize);
if (data == nullptr) { if (data == nullptr) {
return nullptr; return dv::none;
} }
auto map = json::from_binary(data, bytesSize); auto map = json::from_binary(data, bytesSize);
if (map->size() == 0) { if (map.size() == 0) {
return nullptr; return dv::none;
} }
return map; return map;
} }

View File

@ -8,7 +8,6 @@
#include <mutex> #include <mutex>
#include <unordered_map> #include <unordered_map>
#include "data/dynamic_fwd.hpp"
#include "typedefs.hpp" #include "typedefs.hpp"
#include "util/BufferPool.hpp" #include "util/BufferPool.hpp"
#include "voxels/Chunk.hpp" #include "voxels/Chunk.hpp"
@ -198,7 +197,7 @@ public:
std::unique_ptr<ubyte[]> getChunk(int x, int z); std::unique_ptr<ubyte[]> getChunk(int x, int z);
std::unique_ptr<light_t[]> getLights(int x, int z); std::unique_ptr<light_t[]> getLights(int x, int z);
chunk_inventories_map fetchInventories(int x, int z); chunk_inventories_map fetchInventories(int x, int z);
dynamic::Map_sptr fetchEntities(int x, int z); dv::value fetchEntities(int x, int z);
void processRegionVoxels(int x, int z, const regionproc& func); void processRegionVoxels(int x, int z, const regionproc& func);

View File

@ -11,7 +11,6 @@
#include "coders/gzip.hpp" #include "coders/gzip.hpp"
#include "coders/json.hpp" #include "coders/json.hpp"
#include "coders/toml.hpp" #include "coders/toml.hpp"
#include "data/dynamic.hpp"
#include "util/stringutil.hpp" #include "util/stringutil.hpp"
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -116,30 +115,30 @@ bool files::write_string(const fs::path& filename, const std::string content) {
} }
bool files::write_json( bool files::write_json(
const fs::path& filename, const dynamic::Map* obj, bool nice const fs::path& filename, const dv::value& obj, bool nice
) { ) {
return files::write_string(filename, json::stringify(obj, nice, " ")); return files::write_string(filename, json::stringify(obj, nice, " "));
} }
bool files::write_binary_json( bool files::write_binary_json(
const fs::path& filename, const dynamic::Map* obj, bool compression const fs::path& filename, const dv::value& obj, bool compression
) { ) {
auto bytes = json::to_binary(obj, compression); auto bytes = json::to_binary(obj, compression);
return files::write_bytes(filename, bytes.data(), bytes.size()); return files::write_bytes(filename, bytes.data(), bytes.size());
} }
std::shared_ptr<dynamic::Map> files::read_json(const fs::path& filename) { dv::value files::read_json(const fs::path& filename) {
std::string text = files::read_string(filename); std::string text = files::read_string(filename);
return json::parse(filename.string(), text); return json::parse(filename.string(), text);
} }
std::shared_ptr<dynamic::Map> files::read_binary_json(const fs::path& file) { dv::value files::read_binary_json(const fs::path& file) {
size_t size; size_t size;
std::unique_ptr<ubyte[]> bytes(files::read_bytes(file, size)); auto bytes = files::read_bytes(file, size);
return json::from_binary(bytes.get(), size); return json::from_binary(bytes.get(), size);
} }
std::shared_ptr<dynamic::Map> files::read_toml(const fs::path& file) { dv::value files::read_toml(const fs::path& file) {
return toml::parse(file.u8string(), files::read_string(file)); return toml::parse(file.u8string(), files::read_string(file));
} }

View File

@ -7,13 +7,10 @@
#include <vector> #include <vector>
#include "typedefs.hpp" #include "typedefs.hpp"
#include "data/dv.hpp"
namespace fs = std::filesystem; namespace fs = std::filesystem;
namespace dynamic {
class Map;
}
namespace files { namespace files {
/// @brief Read-only random access file /// @brief Read-only random access file
class rafile { class rafile {
@ -46,7 +43,7 @@ namespace files {
/// @param nice if true, human readable format will be used, otherwise /// @param nice if true, human readable format will be used, otherwise
/// minimal /// minimal
bool write_json( bool write_json(
const fs::path& filename, const dynamic::Map* obj, bool nice = true const fs::path& filename, const dv::value& obj, bool nice = true
); );
/// @brief Write dynamic data to the binary JSON file /// @brief Write dynamic data to the binary JSON file
@ -54,7 +51,7 @@ namespace files {
/// @param compressed use gzip compression /// @param compressed use gzip compression
bool write_binary_json( bool write_binary_json(
const fs::path& filename, const fs::path& filename,
const dynamic::Map* obj, const dv::value& obj,
bool compressed = false bool compressed = false
); );
@ -65,8 +62,8 @@ namespace files {
/// @brief Read JSON or BJSON file /// @brief Read JSON or BJSON file
/// @param file *.json or *.bjson file /// @param file *.json or *.bjson file
std::shared_ptr<dynamic::Map> read_json(const fs::path& file); dv::value read_json(const fs::path& file);
std::shared_ptr<dynamic::Map> read_binary_json(const fs::path& file); dv::value read_binary_json(const fs::path& file);
std::shared_ptr<dynamic::Map> read_toml(const fs::path& file); dv::value read_toml(const fs::path& file);
std::vector<std::string> read_list(const fs::path& file); std::vector<std::string> read_list(const fs::path& file);
} }

View File

@ -80,12 +80,13 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) {
builder.add("do-write-lights", &settings.debug.doWriteLights); builder.add("do-write-lights", &settings.debug.doWriteLights);
} }
dynamic::Value SettingsHandler::getValue(const std::string& name) const { dv::value SettingsHandler::getValue(const std::string& name) const {
auto found = map.find(name); auto found = map.find(name);
if (found == map.end()) { if (found == map.end()) {
throw std::runtime_error("setting '" + name + "' does not exist"); throw std::runtime_error("setting '" + name + "' does not exist");
} }
auto setting = found->second; auto setting = found->second;
if (auto number = dynamic_cast<NumberSetting*>(setting)) { if (auto number = dynamic_cast<NumberSetting*>(setting)) {
return static_cast<number_t>(number->get()); return static_cast<number_t>(number->get());
} else if (auto integer = dynamic_cast<IntegerSetting*>(setting)) { } else if (auto integer = dynamic_cast<IntegerSetting*>(setting)) {
@ -121,20 +122,26 @@ bool SettingsHandler::has(const std::string& name) const {
} }
template <class T> template <class T>
static void set_numeric_value(T* setting, const dynamic::Value& value) { static void set_numeric_value(T* setting, const dv::value& value) {
if (auto num = std::get_if<integer_t>(&value)) { using dv::value_type;
setting->set(*num);
} else if (auto num = std::get_if<number_t>(&value)) { switch (value.getType()) {
setting->set(*num); case value_type::integer:
} else if (auto flag = std::get_if<bool>(&value)) { setting->set(value.asInteger());
setting->set(*flag); break;
} else { case value_type::number:
throw std::runtime_error("type error, numeric value expected"); setting->set(value.asNumber());
break;
case value_type::boolean:
setting->set(value.asBoolean());
break;
default:
throw std::runtime_error("type error, numeric value expected");
} }
} }
void SettingsHandler::setValue( void SettingsHandler::setValue(
const std::string& name, const dynamic::Value& value const std::string& name, const dv::value& value
) { ) {
auto found = map.find(name); auto found = map.find(name);
if (found == map.end()) { if (found == map.end()) {
@ -148,16 +155,23 @@ void SettingsHandler::setValue(
} else if (auto flag = dynamic_cast<FlagSetting*>(setting)) { } else if (auto flag = dynamic_cast<FlagSetting*>(setting)) {
set_numeric_value(flag, value); set_numeric_value(flag, value);
} else if (auto string = dynamic_cast<StringSetting*>(setting)) { } else if (auto string = dynamic_cast<StringSetting*>(setting)) {
if (auto num = std::get_if<integer_t>(&value)) { using dv::value_type;
string->set(std::to_string(*num));
} else if (auto num = std::get_if<number_t>(&value)) { switch (value.getType()) {
string->set(std::to_string(*num)); case value_type::integer:
} else if (auto flag = std::get_if<bool>(&value)) { string->set(std::to_string(value.asInteger()));
string->set(*flag ? "true" : "false"); break;
} else if (auto str = std::get_if<std::string>(&value)) { case value_type::number:
string->set(*str); string->set(std::to_string(value.asNumber()));
} else { break;
throw std::runtime_error("not implemented for type"); case value_type::boolean:
string->set(value.asBoolean() ? "true" : "false");
break;
case value_type::string:
string->set(value.asString());
break;
default:
throw std::runtime_error("not implemented for type");
} }
} else { } else {
throw std::runtime_error( throw std::runtime_error(

View File

@ -5,7 +5,7 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "data/dynamic.hpp" #include "data/dv.hpp"
class Setting; class Setting;
struct EngineSettings; struct EngineSettings;
@ -21,8 +21,8 @@ class SettingsHandler {
public: public:
SettingsHandler(EngineSettings& settings); SettingsHandler(EngineSettings& settings);
dynamic::Value getValue(const std::string& name) const; dv::value getValue(const std::string& name) const;
void setValue(const std::string& name, const dynamic::Value& value); void setValue(const std::string& name, const dv::value& value);
std::string toString(const std::string& name) const; std::string toString(const std::string& name) const;
Setting* getSetting(const std::string& name) const; Setting* getSetting(const std::string& name) const;
bool has(const std::string& name) const; bool has(const std::string& name) const;

View File

@ -403,14 +403,12 @@ void Hud::closeInventory() {
} }
void Hud::add(const HudElement& element) { void Hud::add(const HudElement& element) {
using namespace dynamic;
gui->add(element.getNode()); gui->add(element.getNode());
auto document = element.getDocument(); auto document = element.getDocument();
if (document) { if (document) {
auto invview = std::dynamic_pointer_cast<InventoryView>(element.getNode()); auto invview = std::dynamic_pointer_cast<InventoryView>(element.getNode());
auto inventory = invview ? invview->getInventory() : nullptr; auto inventory = invview ? invview->getInventory() : nullptr;
std::vector<Value> args; std::vector<dv::value> args;
args.emplace_back(inventory ? inventory.get()->getId() : 0); args.emplace_back(inventory ? inventory.get()->getId() : 0);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
args.emplace_back(static_cast<integer_t>(blockPos[i])); args.emplace_back(static_cast<integer_t>(blockPos[i]));

View File

@ -7,7 +7,7 @@
#include "content/ContentPack.hpp" #include "content/ContentPack.hpp"
#include "files/files.hpp" #include "files/files.hpp"
#include "util/stringutil.hpp" #include "util/stringutil.hpp"
#include "data/dynamic.hpp" #include "data/dv.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
static debug::Logger logger("locale"); static debug::Logger logger("locale");
@ -72,23 +72,21 @@ void langs::loadLocalesInfo(const fs::path& resdir, std::string& fallback) {
auto root = files::read_json(file); auto root = files::read_json(file);
langs::locales_info.clear(); langs::locales_info.clear();
root->str("fallback", fallback); root.at("fallback").get(fallback);
auto langs = root->map("langs"); if (auto found = root.at("langs")) {
if (langs) { auto& langs = *found;
auto logline = logger.info(); auto logline = logger.info();
logline << "locales "; logline << "locales ";
for (auto& entry : langs->values) { for (const auto& [key, langInfo] : langs.asObject()) {
auto langInfo = entry.second;
std::string name; std::string name;
if (auto mapptr = std::get_if<dynamic::Map_sptr>(&langInfo)) { if (langInfo.isObject()) {
name = (*mapptr)->get("name", "none"s); name = langInfo["name"].asString("none");
} else { } else {
continue; continue;
} }
logline << "[" << entry.first << " (" << name << ")] "; logline << "[" << key << " (" << name << ")] ";
langs::locales_info[entry.first] = LocaleInfo {entry.first, name}; langs::locales_info[key] = LocaleInfo {key, name};
} }
logline << "added"; logline << "added";
} }

View File

@ -6,7 +6,7 @@
#include "delegates.hpp" #include "delegates.hpp"
#include "engine.hpp" #include "engine.hpp"
#include "data/dynamic.hpp" #include "data/dv.hpp"
#include "interfaces/Task.hpp" #include "interfaces/Task.hpp"
#include "files/engine_paths.hpp" #include "files/engine_paths.hpp"
#include "graphics/ui/elements/Menu.hpp" #include "graphics/ui/elements/Menu.hpp"
@ -36,9 +36,7 @@ void menus::create_version_label(Engine* engine) {
gui::page_loader_func menus::create_page_loader(Engine* engine) { gui::page_loader_func menus::create_page_loader(Engine* engine) {
return [=](const std::string& query) { return [=](const std::string& query) {
using namespace dynamic; std::vector<dv::value> args;
std::vector<Value> args;
std::string name; std::string name;
size_t index = query.find('?'); size_t index = query.find('?');
@ -46,14 +44,14 @@ gui::page_loader_func menus::create_page_loader(Engine* engine) {
auto argstr = query.substr(index+1); auto argstr = query.substr(index+1);
name = query.substr(0, index); name = query.substr(0, index);
auto map = create_map(); auto map = dv::object();
auto filename = "query for "+name; auto filename = "query for "+name;
BasicParser parser(filename, argstr); BasicParser parser(filename, argstr);
while (parser.hasNext()) { while (parser.hasNext()) {
auto key = std::string(parser.readUntil('=')); auto key = std::string(parser.readUntil('='));
parser.nextChar(); parser.nextChar();
auto value = std::string(parser.readUntil('&')); auto value = std::string(parser.readUntil('&'));
map->put(key, value); map[key] = value;
} }
args.emplace_back(map); args.emplace_back(map);
} else { } else {
@ -106,7 +104,7 @@ bool menus::call(Engine* engine, runnable func) {
} }
} }
UiDocument* menus::show(Engine* engine, const std::string& name, std::vector<dynamic::Value> args) { UiDocument* menus::show(Engine* engine, const std::string& name, std::vector<dv::value> args) {
auto menu = engine->getGUI()->getMenu(); auto menu = engine->getGUI()->getMenu();
auto file = engine->getResPaths()->find("layouts/"+name+".xml"); auto file = engine->getResPaths()->find("layouts/"+name+".xml");
auto fullname = "core:layouts/"+name; auto fullname = "core:layouts/"+name;
@ -123,8 +121,6 @@ UiDocument* menus::show(Engine* engine, const std::string& name, std::vector<dyn
} }
void menus::show_process_panel(Engine* engine, const std::shared_ptr<Task>& task, const std::wstring& text) { void menus::show_process_panel(Engine* engine, const std::shared_ptr<Task>& task, const std::wstring& text) {
using namespace dynamic;
uint initialWork = task->getWorkTotal(); uint initialWork = task->getWorkTotal();
auto menu = engine->getGUI()->getMenu(); auto menu = engine->getGUI()->getMenu();

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "data/dynamic.hpp" #include "data/dv.hpp"
#include "graphics/ui/elements/Menu.hpp" #include "graphics/ui/elements/Menu.hpp"
#include <string> #include <string>
@ -21,7 +21,7 @@ namespace menus {
UiDocument* show( UiDocument* show(
Engine* engine, Engine* engine,
const std::string& name, const std::string& name,
std::vector<dynamic::Value> args std::vector<dv::value> args
); );
void show_process_panel(Engine* engine, const std::shared_ptr<Task>& task, const std::wstring& text=L""); void show_process_panel(Engine* engine, const std::shared_ptr<Task>& task, const std::wstring& text=L"");

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "UINode.hpp" #include "UINode.hpp"
#include "data/dynamic_fwd.hpp"
namespace gui { namespace gui {
class TrackBar : public UINode { class TrackBar : public UINode {

View File

@ -1,12 +1,12 @@
#pragma once #pragma once
#include "coders/json.hpp" #include "data/dv.hpp"
#include <memory> #include <memory>
class Serializable { class Serializable {
public: public:
virtual ~Serializable() { } virtual ~Serializable() {}
virtual std::unique_ptr<dynamic::Map> serialize() const = 0; virtual dv::value serialize() const = 0;
virtual void deserialize(dynamic::Map* src) = 0; virtual void deserialize(const dv::value& src) = 0;
}; };

View File

@ -1,7 +1,6 @@
#include "Inventory.hpp" #include "Inventory.hpp"
#include "content/ContentLUT.hpp" #include "content/ContentLUT.hpp"
#include "data/dynamic.hpp"
Inventory::Inventory(int64_t id, size_t size) : id(id), slots(size) { Inventory::Inventory(int64_t id, size_t size) : id(id), slots(size) {
} }
@ -46,50 +45,52 @@ void Inventory::move(
} }
} }
void Inventory::deserialize(dynamic::Map* src) { void Inventory::deserialize(const dv::value& src) {
id = src->get("id", 1); id = src["id"].asInteger(1);
auto slotsarr = src->list("slots"); auto& slotsarr = src["slots"];
size_t slotscount = slotsarr->size(); size_t slotscount = slotsarr.size();
while (slots.size() < slotscount) { while (slots.size() < slotscount) {
slots.emplace_back(); slots.emplace_back();
} }
for (size_t i = 0; i < slotscount; i++) { for (size_t i = 0; i < slotscount; i++) {
auto item = slotsarr->map(i); auto& item = slotsarr[i];
itemid_t id = item->get("id", ITEM_EMPTY); itemid_t id = item["id"].asInteger();
itemcount_t count = item->get("count", 0); itemcount_t count = 0;
if (item.has("count")){
count = item["count"].asInteger();
}
auto& slot = slots[i]; auto& slot = slots[i];
slot.set(ItemStack(id, count)); slot.set(ItemStack(id, count));
} }
} }
std::unique_ptr<dynamic::Map> Inventory::serialize() const { dv::value Inventory::serialize() const {
auto map = std::make_unique<dynamic::Map>(); auto map = dv::object();
map->put("id", id); map["id"] = id;
auto& slotsarr = map.list("slots");
auto& slotsarr = map->putList("slots");
for (size_t i = 0; i < slots.size(); i++) { for (size_t i = 0; i < slots.size(); i++) {
auto& item = slots[i]; auto& item = slots[i];
itemid_t id = item.getItemId(); itemid_t id = item.getItemId();
itemcount_t count = item.getCount(); itemcount_t count = item.getCount();
auto& slotmap = slotsarr.putMap(); auto& slotmap = slotsarr.object();
slotmap.put("id", id); slotmap["id"] = id;
if (count) { if (count) {
slotmap.put("count", count); slotmap["count"] = count;
} }
} }
return map; return map;
} }
void Inventory::convert(dynamic::Map* data, const ContentLUT* lut) { void Inventory::convert(dv::value& data, const ContentLUT* lut) {
auto slotsarr = data->list("slots"); auto& slotsarr = data["slots"];
for (size_t i = 0; i < slotsarr->size(); i++) { for (auto& item : data["slots"]) {
auto item = slotsarr->map(i); itemid_t id = item["id"].asInteger(ITEM_EMPTY);
itemid_t id = item->get("id", ITEM_EMPTY);
itemid_t replacement = lut->items.getId(id); itemid_t replacement = lut->items.getId(id);
item->put("id", replacement); item["id"] = replacement;
if (replacement == 0 && item->has("count")) { if (replacement == 0 && item.has("count")) {
item->remove("count"); item.erase("count");
} }
} }
} }

View File

@ -7,10 +7,6 @@
#include "typedefs.hpp" #include "typedefs.hpp"
#include "ItemStack.hpp" #include "ItemStack.hpp"
namespace dynamic {
class Map;
}
class ContentLUT; class ContentLUT;
class ContentIndices; class ContentIndices;
@ -37,12 +33,11 @@ public:
size_t end = -1 size_t end = -1
); );
/* deserializing inventory */ void deserialize(const dv::value& src) override;
void deserialize(dynamic::Map* src) override;
/* serializing inventory */
std::unique_ptr<dynamic::Map> serialize() const override;
static void convert(dynamic::Map* data, const ContentLUT* lut); dv::value serialize() const override;
static void convert(dv::value& data, const ContentLUT* lut);
inline void setId(int64_t id) { inline void setId(int64_t id) {
this->id = id; this->id = id;

View File

@ -59,7 +59,7 @@ public:
} }
} }
dynamic::Value parseValue() { dv::value parseValue() {
char c = peek(); char c = peek();
if (is_cmd_identifier_start(c) || c == '@') { if (is_cmd_identifier_start(c) || c == '@') {
auto str = parseIdentifier(true); auto str = parseIdentifier(true);
@ -68,7 +68,7 @@ public:
} else if (str == "false") { } else if (str == "false") {
return false; return false;
} else if (str == "none" || str == "nil" || str == "null") { } else if (str == "none" || str == "nil" || str == "null") {
return dynamic::NONE; return nullptr;
} }
return str; return str;
} }
@ -116,8 +116,8 @@ public:
enumname = parseEnum(); enumname = parseEnum();
} }
bool optional = false; bool optional = false;
dynamic::Value def {}; dv::value def;
dynamic::Value origin {}; dv::value origin;
bool loop = true; bool loop = true;
while (hasNext() && loop) { while (hasNext() && loop) {
char c = peek(); char c = peek();
@ -173,18 +173,17 @@ public:
inline parsing_error typeError( inline parsing_error typeError(
const std::string& argname, const std::string& argname,
const std::string& expected, const std::string& expected,
const dynamic::Value& value const dv::value& value
) { ) {
return argumentError( return argumentError(
argname, expected + " expected, got " + dynamic::type_name(value) argname, expected + " expected, got " + dv::type_name(value)
); );
} }
template <typename T>
inline bool typeCheck( inline bool typeCheck(
Argument* arg, const dynamic::Value& value, const std::string& tname Argument* arg, dv::value_type type, const dv::value& value, const std::string& tname
) { ) {
if (!std::holds_alternative<T>(value)) { if (value.getType() != type) {
if (arg->optional) { if (arg->optional) {
return false; return false;
} else { } else {
@ -194,10 +193,11 @@ public:
return true; return true;
} }
inline bool selectorCheck(Argument* arg, const dynamic::Value& value) { inline bool selectorCheck(Argument* arg, const dv::value& value) {
if (auto string = std::get_if<std::string>(&value)) { if (value.isString()) {
if ((*string)[0] == '@') { const auto& string = value.asString();
if (!util::is_integer((*string).substr(1))) { if (string[0] == '@') {
if (!util::is_integer(string.substr(1))) {
throw argumentError(arg->name, "invalid selector"); throw argumentError(arg->name, "invalid selector");
} }
return true; return true;
@ -210,12 +210,13 @@ public:
} }
} }
bool typeCheck(Argument* arg, const dynamic::Value& value) { bool typeCheck(Argument* arg, const dv::value& value) {
switch (arg->type) { switch (arg->type) {
case ArgType::enumvalue: { case ArgType::enumvalue: {
if (auto* string = std::get_if<std::string>(&value)) { if (value.getType() == dv::value_type::string) {
const auto& string = value.asString();
auto& enumname = arg->enumname; auto& enumname = arg->enumname;
if (enumname.find("|" + *string + "|") == if (enumname.find("|" + string + "|") ==
std::string::npos) { std::string::npos) {
throw error( throw error(
"argument " + util::quote(arg->name) + "argument " + util::quote(arg->name) +
@ -231,7 +232,7 @@ public:
break; break;
} }
case ArgType::number: case ArgType::number:
if (!dynamic::is_numeric(value)) { if (!dv::is_numeric(value)) {
if (arg->optional) { if (arg->optional) {
return false; return false;
} else { } else {
@ -242,9 +243,9 @@ public:
case ArgType::selector: case ArgType::selector:
return selectorCheck(arg, value); return selectorCheck(arg, value);
case ArgType::integer: case ArgType::integer:
return typeCheck<integer_t>(arg, value, "integer"); return typeCheck(arg, dv::value_type::integer, value, "integer");
case ArgType::string: case ArgType::string:
if (!std::holds_alternative<std::string>(value)) { if (!value.isString()) {
return !arg->optional; return !arg->optional;
} }
break; break;
@ -252,36 +253,35 @@ public:
return true; return true;
} }
dynamic::Value fetchOrigin( dv::value fetchOrigin(
CommandsInterpreter* interpreter, Argument* arg CommandsInterpreter* interpreter, Argument* arg
) { ) {
if (dynamic::is_numeric(arg->origin)) { if (dv::is_numeric(arg->origin)) {
return arg->origin; return arg->origin;
} else if (auto string = std::get_if<std::string>(&arg->origin)) { } else if (arg->origin.getType() == dv::value_type::string) {
return (*interpreter)[*string]; return (*interpreter)[arg->origin.asString()];
} }
return dynamic::NONE; return nullptr;
} }
dynamic::Value applyRelative( dv::value applyRelative(
Argument* arg, dynamic::Value value, const dynamic::Value& origin Argument* arg, dv::value value, const dv::value& origin
) { ) {
if (origin.index() == 0) { if (origin == nullptr) {
return value; return value;
} }
try { try {
if (arg->type == ArgType::number) { if (arg->type == ArgType::number) {
return dynamic::get_number(origin) + dynamic::get_number(value); return origin.asNumber() + value.asNumber();
} else { } else {
return dynamic::get_integer(origin) + return origin.asInteger() + value.asInteger();
dynamic::get_integer(value);
} }
} catch (std::runtime_error& err) { } catch (std::runtime_error& err) {
throw argumentError(arg->name, err.what()); throw argumentError(arg->name, err.what());
} }
} }
dynamic::Value parseRelativeValue( dv::value parseRelativeValue(
CommandsInterpreter* interpreter, Argument* arg CommandsInterpreter* interpreter, Argument* arg
) { ) {
if (arg->type != ArgType::number && arg->type != ArgType::integer) { if (arg->type != ArgType::number && arg->type != ArgType::integer) {
@ -293,13 +293,13 @@ public:
return origin; return origin;
} }
auto value = parseValue(); auto value = parseValue();
if (origin.index() == 0) { if (origin == nullptr) {
return value; return value;
} }
return applyRelative(arg, value, origin); return applyRelative(arg, value, origin);
} }
inline dynamic::Value performKeywordArg( inline dv::value performKeywordArg(
CommandsInterpreter* interpreter, CommandsInterpreter* interpreter,
Command* command, Command* command,
const std::string& key const std::string& key
@ -322,14 +322,14 @@ public:
if (command == nullptr) { if (command == nullptr) {
throw error("unknown command " + util::quote(name)); throw error("unknown command " + util::quote(name));
} }
auto args = dynamic::create_list(); auto args = dv::list();
auto kwargs = dynamic::create_map(); auto kwargs = dv::object();
int arg_index = 0; int arg_index = 0;
while (hasNext()) { while (hasNext()) {
bool relative = false; bool relative = false;
dynamic::Value value = dynamic::NONE; dv::value value;
if (peek() == '~') { if (peek() == '~') {
relative = true; relative = true;
value = static_cast<integer_t>(0); value = static_cast<integer_t>(0);
@ -338,18 +338,17 @@ public:
if (hasNext() && peekNoJump() != ' ') { if (hasNext() && peekNoJump() != ' ') {
value = parseValue(); value = parseValue();
if (auto string = std::get_if<std::string>(&value)) { if (value.isString()) {
if ((*string)[0] == '$') { const auto& string = value.asString();
value = (*interpreter)[string->substr(1)]; if (string[0] == '$') {
value = (*interpreter)[string.substr(1)];
} }
} }
// keyword argument // keyword argument
if (!relative && hasNext() && peek() == '=') { if (value.isString() && !relative && hasNext() && peek() == '=') {
auto key = std::get<std::string>(value); const auto& key = value.asString();
kwargs->put( kwargs[key] = performKeywordArg(interpreter, command, key);
key, performKeywordArg(interpreter, command, key)
);
} }
} }
@ -357,21 +356,22 @@ public:
Argument* arg = nullptr; Argument* arg = nullptr;
do { do {
if (arg) { if (arg) {
if (auto string = std::get_if<std::string>(&arg->def)) { if (arg->def.isString()) {
if ((*string)[0] == '$') { const auto& string = arg->def.asString();
args->put((*interpreter)[string->substr(1)]); if (string[0] == '$') {
args.add((*interpreter)[string.substr(1)]);
} else { } else {
args->put(arg->def); args.add(arg->def);
} }
} else { } else {
args->put(arg->def); args.add(arg->def);
} }
} }
arg = command->getArgument(arg_index++); arg = command->getArgument(arg_index++);
if (arg == nullptr) { if (arg == nullptr) {
throw error("extra positional argument"); throw error("extra positional argument");
} }
if (arg->origin.index() && relative) { if (arg->origin != nullptr && relative) {
break; break;
} }
} while (!typeCheck(arg, value)); } while (!typeCheck(arg, value));
@ -380,20 +380,21 @@ public:
value = value =
applyRelative(arg, value, fetchOrigin(interpreter, arg)); applyRelative(arg, value, fetchOrigin(interpreter, arg));
} }
args->put(value); args.add(value);
} }
while (auto arg = command->getArgument(arg_index++)) { while (auto arg = command->getArgument(arg_index++)) {
if (!arg->optional) { if (!arg->optional) {
throw error("missing argument " + util::quote(arg->name)); throw error("missing argument " + util::quote(arg->name));
} else { } else {
if (auto string = std::get_if<std::string>(&arg->def)) { if (arg->def.isString()) {
if ((*string)[0] == '$') { const auto& string = arg->def.asString();
args->put((*interpreter)[string->substr(1)]); if (string[0] == '$') {
args.add((*interpreter)[string.substr(1)]);
continue; continue;
} }
} }
args->put(arg->def); args.add(arg->def);
} }
} }
return Prompt {command, args, kwargs}; return Prompt {command, args, kwargs};

View File

@ -5,7 +5,7 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "data/dynamic.hpp" #include "data/dv.hpp"
namespace cmd { namespace cmd {
enum class ArgType { number, integer, enumvalue, selector, string }; enum class ArgType { number, integer, enumvalue, selector, string };
@ -31,8 +31,8 @@ namespace cmd {
std::string name; std::string name;
ArgType type; ArgType type;
bool optional; bool optional;
dynamic::Value def; dv::value def;
dynamic::Value origin; dv::value origin;
std::string enumname; std::string enumname;
}; };
@ -41,12 +41,12 @@ namespace cmd {
struct Prompt { struct Prompt {
Command* command; Command* command;
dynamic::List_sptr args; // positional arguments list dv::value args; // positional arguments list
dynamic::Map_sptr kwargs; // keyword arguments table dv::value kwargs; // keyword arguments table
}; };
using executor_func = std::function<dynamic::Value( using executor_func = std::function<dv::value(
CommandsInterpreter*, dynamic::List_sptr args, dynamic::Map_sptr kwargs CommandsInterpreter*, dv::value args, dv::value kwargs
)>; )>;
class Command { class Command {
@ -85,7 +85,7 @@ namespace cmd {
return &found->second; return &found->second;
} }
dynamic::Value execute( dv::value execute(
CommandsInterpreter* interpreter, const Prompt& prompt CommandsInterpreter* interpreter, const Prompt& prompt
) { ) {
return executor(interpreter, prompt.args, prompt.kwargs); return executor(interpreter, prompt.args, prompt.kwargs);
@ -127,7 +127,7 @@ namespace cmd {
class CommandsInterpreter { class CommandsInterpreter {
std::unique_ptr<CommandsRepository> repository; std::unique_ptr<CommandsRepository> repository;
std::unordered_map<std::string, dynamic::Value> variables; std::unordered_map<std::string, dv::value> variables;
public: public:
CommandsInterpreter() CommandsInterpreter()
: repository(std::make_unique<CommandsRepository>()) { : repository(std::make_unique<CommandsRepository>()) {
@ -141,15 +141,15 @@ namespace cmd {
Prompt parse(std::string_view text); Prompt parse(std::string_view text);
dynamic::Value execute(std::string_view input) { dv::value execute(std::string_view input) {
return execute(parse(input)); return execute(parse(input));
} }
dynamic::Value execute(const Prompt& prompt) { dv::value execute(const Prompt& prompt) {
return prompt.command->execute(this, prompt); return prompt.command->execute(this, prompt);
} }
dynamic::Value& operator[](const std::string& name) { dv::value& operator[](const std::string& name) {
return variables[name]; return variables[name];
} }

View File

@ -88,14 +88,13 @@ void show_convert_request(
static void show_content_missing( static void show_content_missing(
Engine* engine, const std::shared_ptr<ContentLUT>& lut Engine* engine, const std::shared_ptr<ContentLUT>& lut
) { ) {
using namespace dynamic; auto root = dv::object();
auto root = create_map(); auto& contentEntries = root.list("content");
auto& contentEntries = root->putList("content");
for (auto& entry : lut->getMissingContent()) { for (auto& entry : lut->getMissingContent()) {
std::string contentName = contenttype_name(entry.type); std::string contentName = contenttype_name(entry.type);
auto& contentEntry = contentEntries.putMap(); auto& contentEntry = contentEntries.object();
contentEntry.put("type", contentName); contentEntry["type"] = contentName;
contentEntry.put("name", entry.name); contentEntry["name"] = entry.name;
} }
menus::show(engine, "reports/missing_content", {root}); menus::show(engine, "reports/missing_content", {root});
} }

View File

@ -50,12 +50,9 @@ static int l_spawn(lua::State* L) {
auto defname = lua::tostring(L, 1); auto defname = lua::tostring(L, 1);
auto& def = content->entities.require(defname); auto& def = content->entities.require(defname);
auto pos = lua::tovec3(L, 2); auto pos = lua::tovec3(L, 2);
dynamic::Map_sptr args = nullptr; dv::value args = nullptr;
if (lua::gettop(L) > 2) { if (lua::gettop(L) > 2) {
auto value = lua::tovalue(L, 3); args = lua::tovalue(L, 3);
if (auto map = std::get_if<dynamic::Map_sptr>(&value)) {
args = *map;
}
} }
level->entities->spawn(def, pos, args); level->entities->spawn(def, pos, args);
return 1; return 1;

View File

@ -1,17 +1,12 @@
#include "coders/json.hpp" #include "coders/json.hpp"
#include "data/dynamic.hpp"
#include "api_lua.hpp" #include "api_lua.hpp"
static int l_json_stringify(lua::State* L) { static int l_json_stringify(lua::State* L) {
auto value = lua::tovalue(L, 1); auto value = lua::tovalue(L, 1);
if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) { bool nice = lua::toboolean(L, 2);
bool nice = lua::toboolean(L, 2); auto string = json::stringify(value, nice, " ");
auto string = json::stringify(mapptr->get(), nice, " "); return lua::pushstring(L, string);
return lua::pushstring(L, string);
} else {
throw std::runtime_error("table expected");
}
} }
static int l_json_parse(lua::State* L) { static int l_json_parse(lua::State* L) {

View File

@ -1,5 +1,4 @@
#include "coders/toml.hpp" #include "coders/toml.hpp"
#include "data/dynamic.hpp"
#include "api_lua.hpp" #include "api_lua.hpp"
using namespace scripting; using namespace scripting;
@ -7,8 +6,8 @@ using namespace scripting;
static int l_toml_stringify(lua::State* L) { static int l_toml_stringify(lua::State* L) {
auto value = lua::tovalue(L, 1); auto value = lua::tovalue(L, 1);
if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) { if (value.isObject()) {
auto string = toml::stringify(**mapptr); auto string = toml::stringify(value);
return lua::pushstring(L, string); return lua::pushstring(L, string);
} else { } else {
throw std::runtime_error("table expected"); throw std::runtime_error("table expected");
@ -18,8 +17,7 @@ static int l_toml_stringify(lua::State* L) {
static int l_toml_parse(lua::State* L) { static int l_toml_parse(lua::State* L) {
auto string = lua::require_string(L, 1); auto string = lua::require_string(L, 1);
auto element = toml::parse("<string>", string); auto element = toml::parse("<string>", string);
auto value = std::make_unique<dynamic::Value>(element); return lua::pushvalue(L, element);
return lua::pushvalue(L, *value);
} }
const luaL_Reg tomllib[] = { const luaL_Reg tomllib[] = {

View File

@ -3,7 +3,6 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include "data/dynamic.hpp"
#include "delegates.hpp" #include "delegates.hpp"
#include "logic/scripting/scripting_functional.hpp" #include "logic/scripting/scripting_functional.hpp"
#include "lua_util.hpp" #include "lua_util.hpp"

View File

@ -22,33 +22,42 @@ std::string lua::env_name(int env) {
return "_ENV" + util::mangleid(env); return "_ENV" + util::mangleid(env);
} }
int lua::pushvalue(State* L, const dynamic::Value& value) { int lua::pushvalue(State* L, const dv::value& value) {
using namespace dynamic; using dv::value_type;
if (auto* flag = std::get_if<bool>(&value)) { switch (value.getType()) {
pushboolean(L, *flag); case value_type::none:
} else if (auto* num = std::get_if<integer_t>(&value)) { pushnil(L);
pushinteger(L, *num); break;
} else if (auto* num = std::get_if<number_t>(&value)) { case value_type::boolean:
pushnumber(L, *num); pushboolean(L, value.asBoolean());
} else if (auto* str = std::get_if<std::string>(&value)) { break;
pushstring(L, *str); case value_type::number:
} else if (auto listptr = std::get_if<List_sptr>(&value)) { pushnumber(L, value.asNumber());
auto list = *listptr; break;
createtable(L, list->size(), 0); case value_type::integer:
for (size_t i = 0; i < list->size(); i++) { pushinteger(L, value.asInteger());
pushvalue(L, list->get(i)); break;
rawseti(L, i + 1); case value_type::string:
pushstring(L, value.asString());
break;
case value_type::list: {
createtable(L, value.size(), 0);
size_t index = 1;
for (const auto& elem : value) {
pushvalue(L, elem);
rawseti(L, index);
index++;
}
break;
} }
} else if (auto mapptr = std::get_if<Map_sptr>(&value)) { case value_type::object: {
auto map = *mapptr; createtable(L, 0, value.size());
createtable(L, 0, map->size()); for (const auto& [key, elem] : value.asObject()) {
for (auto& entry : map->values) { pushvalue(L, elem);
pushvalue(L, entry.second); setfield(L, key);
setfield(L, entry.first); }
} }
} else {
pushnil(L);
} }
return 1; return 1;
} }
@ -61,13 +70,13 @@ int lua::pushwstring(State* L, const std::wstring& str) {
return pushstring(L, util::wstr2str_utf8(str)); return pushstring(L, util::wstr2str_utf8(str));
} }
dynamic::Value lua::tovalue(State* L, int idx) { dv::value lua::tovalue(State* L, int idx) {
using namespace dynamic; using dv::value_type;
auto type = lua::type(L, idx); auto type = lua::type(L, idx);
switch (type) { switch (type) {
case LUA_TNIL: case LUA_TNIL:
case LUA_TNONE: case LUA_TNONE:
return dynamic::NONE; return nullptr;
case LUA_TBOOLEAN: case LUA_TBOOLEAN:
return toboolean(L, idx) == 1; return toboolean(L, idx) == 1;
case LUA_TNUMBER: { case LUA_TNUMBER: {
@ -91,22 +100,22 @@ dynamic::Value lua::tovalue(State* L, int idx) {
int len = objlen(L, idx); int len = objlen(L, idx);
if (len) { if (len) {
// array // array
auto list = create_list(); auto list = dv::list();
for (int i = 1; i <= len; i++) { for (int i = 1; i <= len; i++) {
rawgeti(L, i, idx); rawgeti(L, i, idx);
list->put(tovalue(L, -1)); list.add(tovalue(L, -1));
pop(L); pop(L);
} }
return list; return list;
} else { } else {
// table // table
auto map = create_map(); auto map = dv::object();
pushvalue(L, idx); pushvalue(L, idx);
pushnil(L); pushnil(L);
while (next(L, -2)) { while (next(L, -2)) {
pushvalue(L, -2); pushvalue(L, -2);
auto key = tostring(L, -1); auto key = tostring(L, -1);
map->put(key, tovalue(L, -2)); map[key] = tovalue(L, -2);
pop(L, 2); pop(L, 2);
} }
pop(L); pop(L);
@ -219,7 +228,7 @@ runnable lua::create_runnable(State* L) {
scripting::common_func lua::create_lambda(State* L) { scripting::common_func lua::create_lambda(State* L) {
auto funcptr = create_lambda_handler(L); auto funcptr = create_lambda_handler(L);
return [=](const std::vector<dynamic::Value>& args) { return [=](const std::vector<dv::value>& args) -> dv::value {
getglobal(L, LAMBDAS_TABLE); getglobal(L, LAMBDAS_TABLE);
getfield(L, *funcptr); getfield(L, *funcptr);
for (const auto& arg : args) { for (const auto& arg : args) {
@ -230,7 +239,7 @@ scripting::common_func lua::create_lambda(State* L) {
pop(L); pop(L);
return result; return result;
} }
return dynamic::Value(dynamic::NONE); return nullptr;
}; };
} }

View File

@ -4,6 +4,7 @@
#include <typeinfo> #include <typeinfo>
#include <unordered_map> #include <unordered_map>
#include "data/dv.hpp"
#include "lua_wrapper.hpp" #include "lua_wrapper.hpp"
#include "lua_custom_types.hpp" #include "lua_custom_types.hpp"
#define GLM_ENABLE_EXPERIMENTAL #define GLM_ENABLE_EXPERIMENTAL
@ -394,8 +395,8 @@ namespace lua {
return glm::vec4(r / 255, g / 255, b / 255, a / 255); return glm::vec4(r / 255, g / 255, b / 255, a / 255);
} }
int pushvalue(lua::State*, const dynamic::Value& value); int pushvalue(lua::State*, const dv::value& value);
dynamic::Value tovalue(lua::State*, int idx); dv::value tovalue(lua::State*, int idx);
inline bool getfield(lua::State* L, const std::string& name, int idx = -1) { inline bool getfield(lua::State* L, const std::string& name, int idx = -1) {
lua_getfield(L, idx, name.c_str()); lua_getfield(L, idx, name.c_str());

View File

@ -325,7 +325,7 @@ bool scripting::on_item_break_block(
); );
} }
dynamic::Value scripting::get_component_value( dv::value scripting::get_component_value(
const scriptenv& env, const std::string& name const scriptenv& env, const std::string& name
) { ) {
auto L = lua::get_main_thread(); auto L = lua::get_main_thread();
@ -333,15 +333,15 @@ dynamic::Value scripting::get_component_value(
if (lua::getfield(L, name)) { if (lua::getfield(L, name)) {
return lua::tovalue(L, -1); return lua::tovalue(L, -1);
} }
return dynamic::NONE; return nullptr;
} }
void scripting::on_entity_spawn( void scripting::on_entity_spawn(
const EntityDef&, const EntityDef&,
entityid_t eid, entityid_t eid,
const std::vector<std::unique_ptr<UserComponent>>& components, const std::vector<std::unique_ptr<UserComponent>>& components,
dynamic::Map_sptr args, dv::value args,
dynamic::Map_sptr saved dv::value saved
) { ) {
auto L = lua::get_main_thread(); auto L = lua::get_main_thread();
lua::requireglobal(L, STDCOMP); lua::requireglobal(L, STDCOMP);
@ -364,8 +364,8 @@ void scripting::on_entity_spawn(
if (args != nullptr) { if (args != nullptr) {
std::string compfieldname = component->name; std::string compfieldname = component->name;
util::replaceAll(compfieldname, ":", "__"); util::replaceAll(compfieldname, ":", "__");
if (auto datamap = args->map(compfieldname)) { if (args.has(compfieldname)) {
lua::pushvalue(L, datamap); lua::pushvalue(L, args[compfieldname]);
} else { } else {
lua::createtable(L, 0, 0); lua::createtable(L, 0, 0);
} }
@ -377,8 +377,8 @@ void scripting::on_entity_spawn(
if (saved == nullptr) { if (saved == nullptr) {
lua::createtable(L, 0, 0); lua::createtable(L, 0, 0);
} else { } else {
if (auto datamap = saved->map(component->name)) { if (saved.has(component->name)) {
lua::pushvalue(L, datamap); lua::pushvalue(L, saved[component->name]);
} else { } else {
lua::createtable(L, 0, 0); lua::createtable(L, 0, 0);
} }
@ -559,10 +559,10 @@ void scripting::on_entities_render(float delta) {
} }
void scripting::on_ui_open( void scripting::on_ui_open(
UiDocument* layout, std::vector<dynamic::Value> args UiDocument* layout, std::vector<dv::value> args
) { ) {
auto argsptr = auto argsptr =
std::make_shared<std::vector<dynamic::Value>>(std::move(args)); std::make_shared<std::vector<dv::value>>(std::move(args));
std::string name = layout->getId() + ".open"; std::string name = layout->getId() + ".open";
lua::emit_event(lua::get_main_thread(), name, [=](auto L) { lua::emit_event(lua::get_main_thread(), name, [=](auto L) {
for (const auto& value : *argsptr) { for (const auto& value : *argsptr) {

View File

@ -6,7 +6,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "data/dynamic.hpp" #include "data/dv.hpp"
#include "delegates.hpp" #include "delegates.hpp"
#include "typedefs.hpp" #include "typedefs.hpp"
#include "scripting_functional.hpp" #include "scripting_functional.hpp"
@ -87,15 +87,15 @@ namespace scripting {
Player* player, const ItemDef& item, int x, int y, int z Player* player, const ItemDef& item, int x, int y, int z
); );
dynamic::Value get_component_value( dv::value get_component_value(
const scriptenv& env, const std::string& name const scriptenv& env, const std::string& name
); );
void on_entity_spawn( void on_entity_spawn(
const EntityDef& def, const EntityDef& def,
entityid_t eid, entityid_t eid,
const std::vector<std::unique_ptr<UserComponent>>& components, const std::vector<std::unique_ptr<UserComponent>>& components,
dynamic::Map_sptr args, dv::value args,
dynamic::Map_sptr saved dv::value saved
); );
void on_entity_despawn(const Entity& entity); void on_entity_despawn(const Entity& entity);
void on_entity_grounded(const Entity& entity, float force); void on_entity_grounded(const Entity& entity, float force);
@ -111,7 +111,7 @@ namespace scripting {
void on_entity_used(const Entity& entity, Player* player); void on_entity_used(const Entity& entity, Player* player);
/// @brief Called on UI view show /// @brief Called on UI view show
void on_ui_open(UiDocument* layout, std::vector<dynamic::Value> args); void on_ui_open(UiDocument* layout, std::vector<dv::value> args);
void on_ui_progress(UiDocument* layout, int workDone, int totalWork); void on_ui_progress(UiDocument* layout, int workDone, int totalWork);

View File

@ -160,7 +160,7 @@ vec2supplier scripting::create_vec2_supplier(
}; };
} }
dynamic::to_string_func scripting::create_tostring( dv::to_string_func scripting::create_tostring(
const scriptenv& env, const std::string& src, const std::string& file const scriptenv& env, const std::string& src, const std::string& file
) { ) {
auto L = lua::get_main_thread(); auto L = lua::get_main_thread();
@ -168,7 +168,7 @@ dynamic::to_string_func scripting::create_tostring(
lua::loadbuffer(L, *env, src, file); lua::loadbuffer(L, *env, src, file);
lua::call(L, 0, 1); lua::call(L, 0, 1);
auto func = lua::create_lambda(L); auto func = lua::create_lambda(L);
return [func](const dynamic::Value& value) { return [func](const dv::value& value) {
auto result = func({value}); auto result = func({value});
return json::stringify(result, true, " "); return json::stringify(result, true, " ");
}; };

View File

@ -3,13 +3,12 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <string> #include <string>
#include "data/dynamic.hpp" #include "data/dv.hpp"
#include "delegates.hpp" #include "delegates.hpp"
#include "typedefs.hpp" #include "typedefs.hpp"
namespace scripting { namespace scripting {
using common_func = using common_func = std::function<dv::value(const std::vector<dv::value>&)>;
std::function<dynamic::Value(const std::vector<dynamic::Value>&)>;
runnable create_runnable( runnable create_runnable(
const scriptenv& env, const scriptenv& env,
@ -71,7 +70,7 @@ namespace scripting {
const std::string& file = "<string>" const std::string& file = "<string>"
); );
dynamic::to_string_func create_tostring( dv::to_string_func create_tostring(
const scriptenv& env, const scriptenv& env,
const std::string& src, const std::string& src,
const std::string& file = "<string>" const std::string& file = "<string>"

View File

@ -5,7 +5,7 @@
#include "assets/Assets.hpp" #include "assets/Assets.hpp"
#include "content/Content.hpp" #include "content/Content.hpp"
#include "data/dynamic_util.hpp" #include "data/dv_util.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "engine.hpp" #include "engine.hpp"
#include "graphics/core/DrawContext.hpp" #include "graphics/core/DrawContext.hpp"
@ -113,8 +113,8 @@ static void initialize_body(
entityid_t Entities::spawn( entityid_t Entities::spawn(
const EntityDef& def, const EntityDef& def,
glm::vec3 position, glm::vec3 position,
dynamic::Map_sptr args, dv::value args,
dynamic::Map_sptr saved, dv::value saved,
entityid_t uid entityid_t uid
) { ) {
auto skeleton = level->content->getSkeleton(def.skeletonName); auto skeleton = level->content->getSkeleton(def.skeletonName);
@ -166,9 +166,9 @@ entityid_t Entities::spawn(
); );
scripting.components.emplace_back(std::move(component)); scripting.components.emplace_back(std::move(component));
} }
dynamic::Map_sptr componentsMap = nullptr; dv::value componentsMap = nullptr;
if (saved) { if (saved != nullptr) {
componentsMap = saved->map("comps"); componentsMap = saved["comps"];
loadEntity(saved, get(id).value()); loadEntity(saved, get(id).value());
} }
body.hitbox.position = tsf.pos; body.hitbox.position = tsf.pos;
@ -188,54 +188,54 @@ void Entities::despawn(entityid_t id) {
} }
} }
void Entities::loadEntity(const dynamic::Map_sptr& map) { void Entities::loadEntity(const dv::value& map) {
entityid_t uid = 0; entityid_t uid = map["uid"].asInteger();
std::string defname; std::string defname = map["def"].asString();
map->num("uid", uid);
map->str("def", defname);
if (uid == 0) {
throw std::runtime_error("could not read entity - invalid UID");
}
auto& def = level->content->entities.require(defname); auto& def = level->content->entities.require(defname);
spawn(def, {}, nullptr, map, uid); spawn(def, {}, nullptr, map, uid);
} }
void Entities::loadEntity(const dynamic::Map_sptr& map, Entity entity) { void Entities::loadEntity(const dv::value& map, Entity entity) {
auto& transform = entity.getTransform(); auto& transform = entity.getTransform();
auto& body = entity.getRigidbody(); auto& body = entity.getRigidbody();
auto& skeleton = entity.getSkeleton(); auto& skeleton = entity.getSkeleton();
if (auto bodymap = map->map(COMP_RIGIDBODY)) { if (map.has(COMP_RIGIDBODY)) {
dynamic::get_vec(bodymap, "vel", body.hitbox.velocity); auto& bodymap = map[COMP_RIGIDBODY];
dv::get_vec(bodymap, "vel", body.hitbox.velocity);
std::string bodyTypeName; std::string bodyTypeName;
bodymap->str("type", bodyTypeName); map.at("type").get(bodyTypeName);
if (auto bodyType = BodyType_from(bodyTypeName)) { if (auto bodyType = BodyType_from(bodyTypeName)) {
body.hitbox.type = *bodyType; body.hitbox.type = *bodyType;
} }
bodymap->flag("crouch", body.hitbox.crouching); bodymap["crouch"].asBoolean(body.hitbox.crouching);
bodymap->num("damping", body.hitbox.linearDamping); bodymap["damping"].asNumber(body.hitbox.linearDamping);
} }
if (auto tsfmap = map->map(COMP_TRANSFORM)) { if (map.has(COMP_TRANSFORM)) {
dynamic::get_vec(tsfmap, "pos", transform.pos); auto& tsfmap = map[COMP_TRANSFORM];
dynamic::get_vec(tsfmap, "size", transform.size); dv::get_vec(tsfmap, "pos", transform.pos);
dynamic::get_mat(tsfmap, "rot", transform.rot); dv::get_vec(tsfmap, "size", transform.size);
dv::get_mat(tsfmap, "rot", transform.rot);
} }
std::string skeletonName = skeleton.config->getName(); std::string skeletonName = skeleton.config->getName();
map->str("skeleton", skeletonName); map.at("skeleton").get(skeletonName);
if (skeletonName != skeleton.config->getName()) { if (skeletonName != skeleton.config->getName()) {
skeleton.config = level->content->getSkeleton(skeletonName); skeleton.config = level->content->getSkeleton(skeletonName);
} }
if (auto skeletonmap = map->map(COMP_SKELETON)) { if (auto found = map.at(COMP_SKELETON)) {
if (auto texturesmap = skeletonmap->map("textures")) { auto& skeletonmap = *found;
for (auto& [slot, _] : texturesmap->values) { if (auto found = skeletonmap.at("textures")) {
texturesmap->str(slot, skeleton.textures[slot]); auto& texturesmap = *found;
for (auto& [slot, _] : texturesmap.asObject()) {
texturesmap.at(slot).get(skeleton.textures[slot]);
} }
} }
if (auto posearr = skeletonmap->list("pose")) { if (auto found = skeletonmap.at("pose")) {
auto& posearr = *found;
for (size_t i = 0; for (size_t i = 0;
i < std::min(skeleton.pose.matrices.size(), posearr->size()); i < std::min(skeleton.pose.matrices.size(), posearr.size());
i++) { i++) {
dynamic::get_mat(posearr, i, skeleton.pose.matrices[i]); dv::get_mat(posearr[i], skeleton.pose.matrices[i]);
} }
} }
} }
@ -272,12 +272,12 @@ std::optional<Entities::RaycastResult> Entities::rayCast(
} }
} }
void Entities::loadEntities(dynamic::Map_sptr root) { void Entities::loadEntities(dv::value root) {
clean(); clean();
auto list = root->list("data"); auto& list = root["data"];
for (size_t i = 0; i < list->size(); i++) { for (auto& map : list) {
try { try {
loadEntity(list->map(i)); loadEntity(map);
} catch (const std::runtime_error& err) { } catch (const std::runtime_error& err) {
logger.error() << "could not read entity: " << err.what(); logger.error() << "could not read entity: " << err.what();
} }
@ -288,82 +288,82 @@ void Entities::onSave(const Entity& entity) {
scripting::on_entity_save(entity); scripting::on_entity_save(entity);
} }
dynamic::Value Entities::serialize(const Entity& entity) { dv::value Entities::serialize(const Entity& entity) {
auto root = dynamic::create_map(); auto root = dv::object();
auto& eid = entity.getID(); auto& eid = entity.getID();
auto& def = eid.def; auto& def = eid.def;
root->put("def", def.name); root["def"] = def.name;
root->put("uid", eid.uid); root["uid"] = eid.uid;
{ {
auto& transform = entity.getTransform(); auto& transform = entity.getTransform();
auto& tsfmap = root->putMap(COMP_TRANSFORM); auto& tsfmap = root.object(COMP_TRANSFORM);
tsfmap.put("pos", dynamic::to_value(transform.pos)); tsfmap["pos"] = dv::to_value(transform.pos);
if (transform.size != glm::vec3(1.0f)) { if (transform.size != glm::vec3(1.0f)) {
tsfmap.put("size", dynamic::to_value(transform.size)); tsfmap["size"] = dv::to_value(transform.size);
} }
if (transform.rot != glm::mat3(1.0f)) { if (transform.rot != glm::mat3(1.0f)) {
tsfmap.put("rot", dynamic::to_value(transform.rot)); tsfmap["rot"] = dv::to_value(transform.rot);
} }
} }
{ {
auto& rigidbody = entity.getRigidbody(); auto& rigidbody = entity.getRigidbody();
auto& hitbox = rigidbody.hitbox; auto& hitbox = rigidbody.hitbox;
auto& bodymap = root->putMap(COMP_RIGIDBODY); auto& bodymap = root.object(COMP_RIGIDBODY);
if (!rigidbody.enabled) { if (!rigidbody.enabled) {
bodymap.put("enabled", rigidbody.enabled); bodymap["enabled"] = false;
} }
if (def.save.body.velocity) { if (def.save.body.velocity) {
bodymap.put("vel", dynamic::to_value(rigidbody.hitbox.velocity)); bodymap["vel"] = dv::to_value(rigidbody.hitbox.velocity);
} }
if (def.save.body.settings) { if (def.save.body.settings) {
bodymap.put("damping", rigidbody.hitbox.linearDamping); bodymap["damping"] = rigidbody.hitbox.linearDamping;
if (hitbox.type != def.bodyType) { if (hitbox.type != def.bodyType) {
bodymap.put("type", to_string(hitbox.type)); bodymap["type"] = to_string(hitbox.type);
} }
if (hitbox.crouching) { if (hitbox.crouching) {
bodymap.put("crouch", hitbox.crouching); bodymap["crouch"] = hitbox.crouching;
} }
} }
} }
auto& skeleton = entity.getSkeleton(); auto& skeleton = entity.getSkeleton();
if (skeleton.config->getName() != def.skeletonName) { if (skeleton.config->getName() != def.skeletonName) {
root->put("skeleton", skeleton.config->getName()); root["skeleton"] = skeleton.config->getName();
} }
if (def.save.skeleton.pose || def.save.skeleton.textures) { if (def.save.skeleton.pose || def.save.skeleton.textures) {
auto& skeletonmap = root->putMap(COMP_SKELETON); auto& skeletonmap = root.object(COMP_SKELETON);
if (def.save.skeleton.textures) { if (def.save.skeleton.textures) {
auto& map = skeletonmap.putMap("textures"); auto& map = skeletonmap.object("textures");
for (auto& [slot, texture] : skeleton.textures) { for (auto& [slot, texture] : skeleton.textures) {
map.put(slot, texture); map[slot] = texture;
} }
} }
if (def.save.skeleton.pose) { if (def.save.skeleton.pose) {
auto& list = skeletonmap.putList("pose"); auto& list = skeletonmap.list("pose");
for (auto& mat : skeleton.pose.matrices) { for (auto& mat : skeleton.pose.matrices) {
list.put(dynamic::to_value(mat)); list.add(dv::to_value(mat));
} }
} }
} }
auto& scripts = entity.getScripting(); auto& scripts = entity.getScripting();
if (!scripts.components.empty()) { if (!scripts.components.empty()) {
auto& compsMap = root->putMap("comps"); auto& compsMap = root.object("comps");
for (auto& comp : scripts.components) { for (auto& comp : scripts.components) {
auto data = auto data =
scripting::get_component_value(comp->env, SAVED_DATA_VARNAME); scripting::get_component_value(comp->env, SAVED_DATA_VARNAME);
compsMap.put(comp->name, data); compsMap[comp->name] = data;
} }
} }
return root; return root;
} }
dynamic::List_sptr Entities::serialize(const std::vector<Entity>& entities) { dv::value Entities::serialize(const std::vector<Entity>& entities) {
auto list = dynamic::create_list(); auto list = dv::list();
for (auto& entity : entities) { for (auto& entity : entities) {
if (!entity.getDef().save.enabled) { if (!entity.getDef().save.enabled) {
continue; continue;
} }
level->entities->onSave(entity); level->entities->onSave(entity);
list->put(level->entities->serialize(entity)); list.add(level->entities->serialize(entity));
} }
return list; return list;
} }

View File

@ -5,7 +5,7 @@
#include <optional> #include <optional>
#include <vector> #include <vector>
#include "data/dynamic.hpp" #include "data/dv.hpp"
#include "physics/Hitbox.hpp" #include "physics/Hitbox.hpp"
#include "typedefs.hpp" #include "typedefs.hpp"
#include "util/Clock.hpp" #include "util/Clock.hpp"
@ -204,8 +204,8 @@ public:
entityid_t spawn( entityid_t spawn(
const EntityDef& def, const EntityDef& def,
glm::vec3 position, glm::vec3 position,
dynamic::Map_sptr args = nullptr, dv::value args = nullptr,
dynamic::Map_sptr saved = nullptr, dv::value saved = nullptr,
entityid_t uid = 0 entityid_t uid = 0
); );
@ -231,17 +231,17 @@ public:
entityid_t ignore = -1 entityid_t ignore = -1
); );
void loadEntities(dynamic::Map_sptr map); void loadEntities(dv::value map);
void loadEntity(const dynamic::Map_sptr& map); void loadEntity(const dv::value& map);
void loadEntity(const dynamic::Map_sptr& map, Entity entity); void loadEntity(const dv::value& map, Entity entity);
void onSave(const Entity& entity); void onSave(const Entity& entity);
bool hasBlockingInside(AABB aabb); bool hasBlockingInside(AABB aabb);
std::vector<Entity> getAllInside(AABB aabb); std::vector<Entity> getAllInside(AABB aabb);
std::vector<Entity> getAllInRadius(glm::vec3 center, float radius); std::vector<Entity> getAllInRadius(glm::vec3 center, float radius);
void despawn(entityid_t id); void despawn(entityid_t id);
void despawn(std::vector<Entity> entities); void despawn(std::vector<Entity> entities);
dynamic::Value serialize(const Entity& entity); dv::value serialize(const Entity& entity);
dynamic::List_sptr serialize(const std::vector<Entity>& entities); dv::value serialize(const std::vector<Entity>& entities);
void setNextID(entityid_t id) { void setNextID(entityid_t id) {
nextID = id; nextID = id;

View File

@ -256,92 +256,71 @@ glm::vec3 Player::getSpawnPoint() const {
return spawnpoint; return spawnpoint;
} }
std::unique_ptr<dynamic::Map> Player::serialize() const { dv::value Player::serialize() const {
auto root = std::make_unique<dynamic::Map>(); auto root = dv::object();
auto& posarr = root->putList("position");
posarr.put(position.x);
posarr.put(position.y);
posarr.put(position.z);
auto& rotarr = root->putList("rotation"); root["position"] = dv::list({position.x, position.y, position.z});
rotarr.put(cam.x); root["rotation"] = dv::list({cam.x, cam.y, cam.z});
rotarr.put(cam.y); root["spawnpoint"] = dv::list({spawnpoint.x, spawnpoint.y, spawnpoint.z});
rotarr.put(cam.z);
auto& sparr = root->putList("spawnpoint"); root["flight"] = flight;
sparr.put(spawnpoint.x); root["noclip"] = noclip;
sparr.put(spawnpoint.y); root["chosen-slot"] = chosenSlot;
sparr.put(spawnpoint.z); root["entity"] = eid;
root["inventory"] = inventory->serialize();
root->put("flight", flight);
root->put("noclip", noclip);
root->put("chosen-slot", chosenSlot);
root->put("entity", eid);
root->put("inventory", inventory->serialize());
auto found = auto found =
std::find(level->cameras.begin(), level->cameras.end(), currentCamera); std::find(level->cameras.begin(), level->cameras.end(), currentCamera);
if (found != level->cameras.end()) { if (found != level->cameras.end()) {
root->put( root["camera"] = level->content->getIndices(ResourceType::CAMERA)
"camera", .getName(found - level->cameras.begin());
level->content->getIndices(ResourceType::CAMERA)
.getName(found - level->cameras.begin())
);
} }
return root; return root;
} }
void Player::deserialize(dynamic::Map* src) { void Player::deserialize(const dv::value& src) {
auto posarr = src->list("position"); const auto& posarr = src["position"];
position.x = posarr->num(0); position.x = posarr[0].asNumber();
position.y = posarr->num(1); position.y = posarr[1].asNumber();
position.z = posarr->num(2); position.z = posarr[2].asNumber();
camera->position = position; camera->position = position;
auto rotarr = src->list("rotation"); const auto& rotarr = src["rotation"];
cam.x = rotarr->num(0); cam.x = rotarr[0].asNumber();
cam.y = rotarr->num(1); cam.y = rotarr[1].asNumber();
if (rotarr->size() > 2) { cam.z = rotarr[2].asNumber();
cam.z = rotarr->num(2);
const auto& sparr = src["spawnpoint"];
setSpawnPoint(glm::vec3(
sparr[0].asNumber(), sparr[1].asNumber(), sparr[2].asNumber()));
flight = src["flight"].asBoolean();
noclip = src["noclip"].asBoolean();
setChosenSlot(src["chosen-slot"].asInteger());
eid = src["entity"].asNumber();
if (src.has("inventory")) {
getInventory()->deserialize(src["inventory"]);
} }
if (src->has("spawnpoint")) { if (src.has("camera")) {
auto sparr = src->list("spawnpoint"); std::string name = src["camera"].asString();
setSpawnPoint(glm::vec3(sparr->num(0), sparr->num(1), sparr->num(2)));
} else {
setSpawnPoint(position);
}
src->flag("flight", flight);
src->flag("noclip", noclip);
setChosenSlot(src->get("chosen-slot", getChosenSlot()));
src->num("entity", eid);
if (auto invmap = src->map("inventory")) {
getInventory()->deserialize(invmap.get());
}
if (src->has("camera")) {
std::string name;
src->str("camera", name);
if (auto camera = level->getCamera(name)) { if (auto camera = level->getCamera(name)) {
currentCamera = camera; currentCamera = camera;
} }
} }
} }
void Player::convert(dynamic::Map* data, const ContentLUT* lut) { void Player::convert(dv::value& data, const ContentLUT* lut) {
auto players = data->list("players"); if (data.has("players")) {
if (players) { auto& players = data["players"];
for (uint i = 0; i < players->size(); i++) { for (uint i = 0; i < players.size(); i++) {
auto playerData = players->map(i); auto& playerData = players[i];
if (auto inventory = playerData->map("inventory")) { if (playerData.has("inventory")) {
Inventory::convert(inventory.get(), lut); Inventory::convert(playerData["inventory"], lut);
} }
} }
} else { } else if (data.has("inventory")){
if (auto inventory = data->map("inventory")) { Inventory::convert(data["inventory"], lut);
Inventory::convert(inventory.get(), lut);
}
} }
} }

View File

@ -4,7 +4,6 @@
#include <memory> #include <memory>
#include <optional> #include <optional>
#include "data/dynamic.hpp"
#include "interfaces/Object.hpp" #include "interfaces/Object.hpp"
#include "interfaces/Serializable.hpp" #include "interfaces/Serializable.hpp"
#include "settings.hpp" #include "settings.hpp"
@ -103,10 +102,10 @@ public:
void setSpawnPoint(glm::vec3 point); void setSpawnPoint(glm::vec3 point);
glm::vec3 getSpawnPoint() const; glm::vec3 getSpawnPoint() const;
std::unique_ptr<dynamic::Map> serialize() const override; dv::value serialize() const override;
void deserialize(dynamic::Map* src) override; void deserialize(const dv::value& src) override;
static void convert(dynamic::Map* data, const ContentLUT* lut); static void convert(dv::value& data, const ContentLUT* lut);
inline int getId() const { inline int getId() const {
return objectUID; return objectUID;

View File

@ -2,7 +2,7 @@
#include "assets/Assets.hpp" #include "assets/Assets.hpp"
#include "coders/json.hpp" #include "coders/json.hpp"
#include "data/dynamic_util.hpp" #include "data/dv_util.hpp"
#include "graphics/core/Model.hpp" #include "graphics/core/Model.hpp"
#include "graphics/render/ModelBatch.hpp" #include "graphics/render/ModelBatch.hpp"
@ -139,25 +139,23 @@ Bone* SkeletonConfig::find(std::string_view str) const {
} }
static std::tuple<size_t, std::unique_ptr<Bone>> read_node( static std::tuple<size_t, std::unique_ptr<Bone>> read_node(
const dynamic::Map_sptr& root, size_t index const dv::value& root, size_t index
) { ) {
std::string name; std::string name;
std::string model; std::string model;
root->str("name", name); root.at("name").get(name);
root->str("model", model); root.at("model").get(model);
glm::vec3 offset(0.0f); glm::vec3 offset(0.0f);
dynamic::get_vec(root, "offset", offset); dv::get_vec(root, "offset", offset);
std::vector<std::unique_ptr<Bone>> bones; std::vector<std::unique_ptr<Bone>> bones;
size_t count = 1; size_t count = 1;
if (auto nodesList = root->list("nodes")) { if (auto found = root.at("nodes")) {
for (size_t i = 0; i < nodesList->size(); i++) { const auto& nodesList = *found;
if (const auto& map = nodesList->map(i)) { for (const auto& map : nodesList) {
auto [subcount, subNode] = read_node(map, index + count); auto [subcount, subNode] = read_node(map, index + count);
count += subcount; count += subcount;
bones.push_back(std::move(subNode)); bones.push_back(std::move(subNode));
}
} }
} }
return { return {
@ -169,10 +167,7 @@ std::unique_ptr<SkeletonConfig> SkeletonConfig::parse(
std::string_view src, std::string_view file, std::string_view name std::string_view src, std::string_view file, std::string_view name
) { ) {
auto root = json::parse(file, src); auto root = json::parse(file, src);
auto rootNodeMap = root->map("root"); auto rootNodeMap = root["root"];
if (rootNodeMap == nullptr) {
throw std::runtime_error("missing 'root' element");
}
auto [count, rootNode] = read_node(rootNodeMap, 0); auto [count, rootNode] = read_node(rootNodeMap, 0);
return std::make_unique<SkeletonConfig>( return std::make_unique<SkeletonConfig>(
std::string(name), std::move(rootNode), count std::string(name), std::move(rootNode), count

View File

@ -15,10 +15,6 @@ class Lightmap;
class ContentLUT; class ContentLUT;
class Inventory; class Inventory;
namespace dynamic {
class Map;
}
using chunk_inventories_map = using chunk_inventories_map =
std::unordered_map<uint, std::shared_ptr<Inventory>>; std::unordered_map<uint, std::shared_ptr<Inventory>>;

View File

@ -746,8 +746,8 @@ void Chunks::save(Chunk* chunk) {
) )
); );
auto entities = level->entities->getAllInside(aabb); auto entities = level->entities->getAllInside(aabb);
auto root = dynamic::create_map(); auto root = dv::object();
root->put("data", level->entities->serialize(entities)); root["data"] = level->entities->serialize(entities);
if (!entities.empty()) { if (!entities.empty()) {
level->entities->despawn(std::move(entities)); level->entities->despawn(std::move(entities));
chunk->flags.entities = true; chunk->flags.entities = true;

View File

@ -66,8 +66,9 @@ std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
auto invs = regions.fetchInventories(chunk->x, chunk->z); auto invs = regions.fetchInventories(chunk->x, chunk->z);
chunk->setBlockInventories(std::move(invs)); chunk->setBlockInventories(std::move(invs));
if (auto map = regions.fetchEntities(chunk->x, chunk->z)) { auto entitiesData = regions.fetchEntities(chunk->x, chunk->z);
level->entities->loadEntities(std::move(map)); if (entitiesData.getType() == dv::value_type::object) {
level->entities->loadEntities(std::move(entitiesData));
chunk->flags.entities = true; chunk->flags.entities = true;
} }

View File

@ -167,10 +167,9 @@ void Events::setPosition(float xpos, float ypos) {
#include "coders/json.hpp" #include "coders/json.hpp"
#include "coders/toml.hpp" #include "coders/toml.hpp"
#include "data/dynamic.hpp"
std::string Events::writeBindings() { std::string Events::writeBindings() {
dynamic::Map obj; auto obj = dv::object();
for (auto& entry : Events::bindings) { for (auto& entry : Events::bindings) {
const auto& binding = entry.second; const auto& binding = entry.second;
std::string value; std::string value;
@ -188,7 +187,7 @@ std::string Events::writeBindings() {
default: default:
throw std::runtime_error("unsupported control type"); throw std::runtime_error("unsupported control type");
} }
obj.put(entry.first, value); obj[entry.first] = std::move(value);
} }
return toml::stringify(obj); return toml::stringify(obj);
} }
@ -197,26 +196,22 @@ void Events::loadBindings(
const std::string& filename, const std::string& source const std::string& filename, const std::string& source
) { ) {
auto map = toml::parse(filename, source); auto map = toml::parse(filename, source);
for (auto& entry : map->values) { for (auto& [key, value] : map.asObject()) {
if (auto value = std::get_if<std::string>(&entry.second)) { auto [prefix, codename] = util::split_at(value.asString(), ':');
auto [prefix, codename] = util::split_at(*value, ':'); inputtype type;
inputtype type; int code;
int code; if (prefix == "key") {
if (prefix == "key") { type = inputtype::keyboard;
type = inputtype::keyboard; code = static_cast<int>(input_util::keycode_from(codename));
code = static_cast<int>(input_util::keycode_from(codename)); } else if (prefix == "mouse") {
} else if (prefix == "mouse") { type = inputtype::mouse;
type = inputtype::mouse; code = static_cast<int>(input_util::mousecode_from(codename));
code = static_cast<int>(input_util::mousecode_from(codename));
} else {
logger.error()
<< "unknown input type: " << prefix << " (binding "
<< util::quote(entry.first) << ")";
continue;
}
Events::bind(entry.first, type, code);
} else { } else {
logger.error() << "invalid binding entry: " << entry.first; logger.error()
<< "unknown input type: " << prefix << " (binding "
<< util::quote(key) << ")";
continue;
} }
Events::bind(key, type, code);
} }
} }

View File

@ -1,7 +1,7 @@
#include "Level.hpp" #include "Level.hpp"
#include "content/Content.hpp" #include "content/Content.hpp"
#include "data/dynamic_util.hpp" #include "data/dv_util.hpp"
#include "items/Inventories.hpp" #include "items/Inventories.hpp"
#include "items/Inventory.hpp" #include "items/Inventory.hpp"
#include "lighting/Lighting.hpp" #include "lighting/Lighting.hpp"
@ -33,14 +33,15 @@ Level::Level(
auto& cameraIndices = content->getIndices(ResourceType::CAMERA); auto& cameraIndices = content->getIndices(ResourceType::CAMERA);
for (size_t i = 0; i < cameraIndices.size(); i++) { for (size_t i = 0; i < cameraIndices.size(); i++) {
auto camera = std::make_shared<Camera>(); auto camera = std::make_shared<Camera>();
if (auto map = cameraIndices.getSavedData(i)) { auto map = cameraIndices.getSavedData(i);
dynamic::get_vec(map, "pos", camera->position); if (map != nullptr) {
dynamic::get_mat(map, "rot", camera->rotation); dv::get_vec(map, "pos", camera->position);
map->flag("perspective", camera->perspective); dv::get_mat(map, "rot", camera->rotation);
map->flag("flipped", camera->flipped); map.at("perspective").get(camera->perspective);
map->num("zoom", camera->zoom); map.at("flipped").get(camera->flipped);
map.at("zoom").get(camera->zoom);
float fov = camera->getFov(); float fov = camera->getFov();
map->num("fov", fov); map.at("fov").get(fov);
camera->setFov(fov); camera->setFov(fov);
} }
camera->updateVectors(); camera->updateVectors();
@ -99,13 +100,13 @@ void Level::onSave() {
auto& cameraIndices = content->getIndices(ResourceType::CAMERA); auto& cameraIndices = content->getIndices(ResourceType::CAMERA);
for (size_t i = 0; i < cameraIndices.size(); i++) { for (size_t i = 0; i < cameraIndices.size(); i++) {
auto& camera = *cameras.at(i); auto& camera = *cameras.at(i);
auto map = dynamic::create_map(); auto map = dv::object();
map->put("pos", dynamic::to_value(camera.position)); map["pos"] = dv::to_value(camera.position);
map->put("rot", dynamic::to_value(camera.rotation)); map["rot"] = dv::to_value(camera.rotation);
map->put("perspective", camera.perspective); map["perspective"] = camera.perspective;
map->put("flipped", camera.flipped); map["flipped"] = camera.flipped;
map->put("zoom", camera.zoom); map["zoom"] = camera.zoom;
map->put("fov", camera.getFov()); map["fov"] = camera.getFov();
cameraIndices.saveData(i, std::move(map)); cameraIndices.saveData(i, std::move(map));
} }
} }

View File

@ -45,20 +45,21 @@ void World::updateTimers(float delta) {
} }
void World::writeResources(const Content* content) { void World::writeResources(const Content* content) {
auto root = dynamic::Map(); auto root = dv::object();
for (size_t typeIndex = 0; typeIndex < RESOURCE_TYPES_COUNT; typeIndex++) { for (size_t typeIndex = 0; typeIndex < RESOURCE_TYPES_COUNT; typeIndex++) {
auto typeName = to_string(static_cast<ResourceType>(typeIndex)); auto typeName = to_string(static_cast<ResourceType>(typeIndex));
auto& list = root.putList(typeName); auto& list = root.list(typeName);
auto& indices = content->resourceIndices[typeIndex]; auto& indices = content->resourceIndices[typeIndex];
for (size_t i = 0; i < indices.size(); i++) { for (size_t i = 0; i < indices.size(); i++) {
auto& map = list.putMap(); auto& map = list.object();
map.put("name", indices.getName(i)); map["name"] = indices.getName(i);
if (auto data = indices.getSavedData(i)) { auto data = indices.getSavedData(i);
map.put("saved", data); if (data != nullptr) {
map["saved"] = data;
} }
} }
} }
files::write_json(wfile->getResourcesFile(), &root); files::write_json(wfile->getResourcesFile(), root);
} }
void World::write(Level* level) { void World::write(Level* level) {
@ -67,14 +68,14 @@ void World::write(Level* level) {
info.nextEntityId = level->entities->peekNextID(); info.nextEntityId = level->entities->peekNextID();
wfile->write(this, content); wfile->write(this, content);
auto playerFile = dynamic::Map(); auto playerFile = dv::object();
auto& players = playerFile.putList("players"); auto& players = playerFile.list("players");
for (const auto& object : level->objects) { for (const auto& object : level->objects) {
if (auto player = std::dynamic_pointer_cast<Player>(object)) { if (auto player = std::dynamic_pointer_cast<Player>(object)) {
players.put(player->serialize()); players.add(player->serialize());
} }
} }
files::write_json(wfile->getPlayerFile(), &playerFile); files::write_json(wfile->getPlayerFile(), playerFile);
writeResources(content); writeResources(content);
} }
@ -129,11 +130,11 @@ std::unique_ptr<Level> World::load(
if (!fs::is_regular_file(file)) { if (!fs::is_regular_file(file)) {
logger.warning() << "player.json does not exists"; logger.warning() << "player.json does not exists";
} else { } else {
auto playerFile = files::read_json(file); auto playerRoot = files::read_json(file);
if (playerFile->has("players")) { if (playerRoot.has("players")) {
level->objects.clear(); level->objects.clear();
auto players = playerFile->list("players"); const auto& players = playerRoot["players"];
for (size_t i = 0; i < players->size(); i++) { for (auto& playerMap : players) {
auto player = level->spawnObject<Player>( auto player = level->spawnObject<Player>(
level.get(), level.get(),
glm::vec3(0, DEF_PLAYER_Y, 0), glm::vec3(0, DEF_PLAYER_Y, 0),
@ -141,12 +142,12 @@ std::unique_ptr<Level> World::load(
level->inventories->create(DEF_PLAYER_INVENTORY_SIZE), level->inventories->create(DEF_PLAYER_INVENTORY_SIZE),
0 0
); );
player->deserialize(players->map(i).get()); player->deserialize(playerMap);
level->inventories->store(player->getInventory()); level->inventories->store(player->getInventory());
} }
} else { } else {
auto player = level->getObject<Player>(0); auto player = level->getObject<Player>(0);
player->deserialize(playerFile.get()); player->deserialize(playerRoot);
level->inventories->store(player->getInventory()); level->inventories->store(player->getInventory());
} }
} }
@ -199,50 +200,52 @@ const std::vector<ContentPack>& World::getPacks() const {
return packs; return packs;
} }
void WorldInfo::deserialize(dynamic::Map* root) { void WorldInfo::deserialize(const dv::value& root) {
name = root->get("name", name); name = root["name"].asString();
generator = root->get("generator", generator); generator = root["generator"].asString(generator);
seed = root->get("seed", seed); seed = root["seed"].asInteger(seed);
if (generator.empty()) { if (generator.empty()) {
generator = WorldGenerators::getDefaultGeneratorID(); generator = WorldGenerators::getDefaultGeneratorID();
} }
if (auto verobj = root->map("version")) { if (root.has("version")) {
verobj->num("major", major); auto& verobj = root["version"];
verobj->num("minor", minor); major = verobj["major"].asInteger();
minor = verobj["minor"].asInteger();
} }
if (auto timeobj = root->map("time")) { if (root.has("time")) {
timeobj->num("day-time", daytime); auto& timeobj = root["time"];
timeobj->num("day-time-speed", daytimeSpeed); daytime = timeobj["day-time"].asNumber();
timeobj->num("total-time", totalTime); daytimeSpeed = timeobj["day-time-speed"].asNumber();
totalTime = timeobj["total-time"].asNumber();
} }
if (auto weatherobj = root->map("weather")) { if (root.has("weather")) {
weatherobj->num("fog", fog); fog = root["weather"]["fog"].asNumber();
} }
nextInventoryId = root->get("next-inventory-id", 2); nextInventoryId = root["next-inventory-id"].asInteger(2);
nextEntityId = root->get("next-entity-id", 1); nextEntityId = root["next-entity-id"].asInteger(1);
} }
std::unique_ptr<dynamic::Map> WorldInfo::serialize() const { dv::value WorldInfo::serialize() const {
auto root = std::make_unique<dynamic::Map>(); auto root = dv::object();
auto& versionobj = root->putMap("version"); auto& versionobj = root.object("version");
versionobj.put("major", ENGINE_VERSION_MAJOR); versionobj["major"] = ENGINE_VERSION_MAJOR;
versionobj.put("minor", ENGINE_VERSION_MINOR); versionobj["minor"] = ENGINE_VERSION_MINOR;
root->put("name", name); root["name"] = name;
root->put("generator", generator); root["generator"] = generator;
root->put("seed", static_cast<integer_t>(seed)); root["seed"] = seed;
auto& timeobj = root->putMap("time"); auto& timeobj = root.object("time");
timeobj.put("day-time", daytime); timeobj["day-time"] = daytime;
timeobj.put("day-time-speed", daytimeSpeed); timeobj["day-time-speed"] = daytimeSpeed;
timeobj.put("total-time", totalTime); timeobj["total-time"] = totalTime;
auto& weatherobj = root->putMap("weather"); auto& weatherobj = root.object("weather");
weatherobj.put("fog", fog); weatherobj["fog"] = fog;
root->put("next-inventory-id", nextInventoryId); root["next-inventory-id"] = nextInventoryId;
root->put("next-entity-id", nextEntityId); root["next-entity-id"] = nextEntityId;
return root; return root;
} }

View File

@ -6,7 +6,6 @@
#include <vector> #include <vector>
#include "content/ContentPack.hpp" #include "content/ContentPack.hpp"
#include "data/dynamic.hpp"
#include "interfaces/Serializable.hpp" #include "interfaces/Serializable.hpp"
#include "typedefs.hpp" #include "typedefs.hpp"
#include "util/timeutil.hpp" #include "util/timeutil.hpp"
@ -48,8 +47,8 @@ struct WorldInfo : public Serializable {
int major = 0, minor = -1; int major = 0, minor = -1;
std::unique_ptr<dynamic::Map> serialize() const override; dv::value serialize() const override;
void deserialize(dynamic::Map* src) override; void deserialize(const dv::value& src) override;
}; };
/// @brief holds all world data except the level (chunks and objects) /// @brief holds all world data except the level (chunks and objects)

View File

@ -1,6 +1,6 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "data/dynamic.hpp" #include "util/Buffer.hpp"
#include "coders/binary_json.hpp" #include "coders/binary_json.hpp"
TEST(BJSON, EncodeDecode) { TEST(BJSON, EncodeDecode) {
@ -8,41 +8,7 @@ TEST(BJSON, EncodeDecode) {
const int bytesSize = 5000; const int bytesSize = 5000;
const int year = 2019; const int year = 2019;
const float score = 3.141592; const float score = 3.141592;
dynamic::ByteBuffer srcBytes(bytesSize); dv::objects::Bytes srcBytes(bytesSize);
for (int i = 0; i < bytesSize; i ++) {
srcBytes[i] = rand();
}
std::vector<ubyte> bjsonBytes;
{
dynamic::Map map;
map.put("name", name);
map.put("year", year);
map.put("score", score);
map.put("data", &srcBytes);
bjsonBytes = json::to_binary(&map, false);
}
{
auto map = json::from_binary(bjsonBytes.data(), bjsonBytes.size());
EXPECT_EQ(map->get<std::string>("name"), name);
EXPECT_EQ(map->get<integer_t>("year"), year);
EXPECT_FLOAT_EQ(map->get<number_t>("score"), score);
auto bytesptr = map->bytes("data");
const auto& bytes = *bytesptr;
EXPECT_EQ(bytes.size(), bytesSize);
for (int i = 0; i < bytesSize; i++) {
EXPECT_EQ(bytes[i], srcBytes[i]);
}
}
}
TEST(BJSON, EncodeDecodeDV) {
const std::string name = "JSON-encoder";
const int bytesSize = 5000;
const int year = 2019;
const float score = 3.141592;
dynamic::ByteBuffer srcBytes(bytesSize);
for (int i = 0; i < bytesSize; i ++) { for (int i = 0; i < bytesSize; i ++) {
srcBytes[i] = rand(); srcBytes[i] = rand();
} }
@ -55,10 +21,10 @@ TEST(BJSON, EncodeDecodeDV) {
object["score"] = score; object["score"] = score;
object["data"] = srcBytes; object["data"] = srcBytes;
bjsonBytes = json::to_binaryDV(object, false); bjsonBytes = json::to_binary(object, false);
} }
{ {
auto object = json::from_binaryDV(bjsonBytes.data(), bjsonBytes.size()); auto object = json::from_binary(bjsonBytes.data(), bjsonBytes.size());
EXPECT_EQ(object["name"].asString(), name); EXPECT_EQ(object["name"].asString(), name);
EXPECT_EQ(object["year"].asInteger(), year); EXPECT_EQ(object["year"].asInteger(), year);

View File

@ -8,42 +8,7 @@ TEST(JSON, EncodeDecode) {
const int bytesSize = 20; const int bytesSize = 20;
const int year = 2019; const int year = 2019;
const float score = 3.141592; const float score = 3.141592;
dynamic::ByteBuffer srcBytes(bytesSize); dv::objects::Bytes srcBytes(bytesSize);
for (int i = 0; i < bytesSize; i ++) {
srcBytes[i] = rand();
}
std::string text;
{
dynamic::Map map;
map.put("name", name);
map.put("year", year);
map.put("score", score);
map.put("data", &srcBytes);
text = json::stringify(&map, false, "");
}
{
auto map = json::parse(text);
EXPECT_EQ(map->get<std::string>("name"), name);
EXPECT_EQ(map->get<integer_t>("year"), year);
EXPECT_FLOAT_EQ(map->get<number_t>("score"), score);
auto b64string = map->get<std::string>("data");
auto bytes = util::base64_decode(b64string);
EXPECT_EQ(bytes.size(), bytesSize);
for (int i = 0; i < bytesSize; i++) {
EXPECT_EQ(bytes[i], srcBytes[i]);
}
}
}
TEST(JSON, EncodeDecodeDV) {
const std::string name = "JSON-encoder";
const int bytesSize = 20;
const int year = 2019;
const float score = 3.141592;
dynamic::ByteBuffer srcBytes(bytesSize);
for (int i = 0; i < bytesSize; i ++) { for (int i = 0; i < bytesSize; i ++) {
srcBytes[i] = rand(); srcBytes[i] = rand();
} }
@ -56,10 +21,10 @@ TEST(JSON, EncodeDecodeDV) {
object["score"] = score; object["score"] = score;
object["data"] = srcBytes; object["data"] = srcBytes;
text = json::stringifyDV(object, false, ""); text = json::stringify(object, false, "");
} }
{ {
auto object = json::parseDV(text); auto object = json::parse(text);
EXPECT_EQ(object["name"].asString(), name); EXPECT_EQ(object["name"].asString(), name);
EXPECT_EQ(object["year"].asInteger(), year); EXPECT_EQ(object["year"].asInteger(), year);
EXPECT_FLOAT_EQ(object["score"].asNumber(), score); EXPECT_FLOAT_EQ(object["score"].asNumber(), score);