diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index a4853606..6ed34baa 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -8,7 +8,6 @@ #include "constants.hpp" #include "content/Content.hpp" #include "content/ContentPack.hpp" -#include "data/dynamic.hpp" #include "debug/Logger.hpp" #include "files/engine_paths.hpp" #include "files/files.hpp" @@ -130,7 +129,7 @@ static std::string assets_def_folder(AssetType tag) { } 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 path = defFolder + "/" + name; @@ -138,36 +137,34 @@ void AssetsLoader::processPreload( add(tag, path, name); return; } - map->str("path", path); + map.at("path").get(path); switch (tag) { - case AssetType::SOUND: + case AssetType::SOUND: { + bool keepPCM = false; add(tag, path, name, - std::make_shared(map->get("keep-pcm", false))); + std::make_shared(map.at("keep-pcm").get(keepPCM))); break; + } default: add(tag, path, name); break; } } -void AssetsLoader::processPreloadList(AssetType tag, dynamic::List* list) { +void AssetsLoader::processPreloadList(AssetType tag, const dv::value& list) { if (list == nullptr) { return; } - for (uint i = 0; i < list->size(); i++) { - auto value = list->get(i); - switch (static_cast(value.index())) { - case dynamic::Type::string: - processPreload(tag, std::get(value), nullptr); + for (const auto& value : list) { + switch (value.getType()) { + case dv::value_type::string: + processPreload(tag, value.asString(), nullptr); break; - case dynamic::Type::map: { - auto map = std::get(value); - auto name = map->get("name"); - processPreload(tag, name, map.get()); + case dv::value_type::object: + processPreload(tag, value["name"].asString(), value); break; - } default: 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) { auto root = files::read_json(file); - processPreloadList(AssetType::ATLAS, root->list("atlases").get()); - processPreloadList(AssetType::FONT, root->list("fonts").get()); - processPreloadList(AssetType::SHADER, root->list("shaders").get()); - processPreloadList(AssetType::TEXTURE, root->list("textures").get()); - processPreloadList(AssetType::SOUND, root->list("sounds").get()); - processPreloadList(AssetType::MODEL, root->list("models").get()); + processPreloadList(AssetType::ATLAS, root["atlases"]); + processPreloadList(AssetType::FONT, root["fonts"]); + processPreloadList(AssetType::SHADER, root["shaders"]); + processPreloadList(AssetType::TEXTURE, root["textures"]); + processPreloadList(AssetType::SOUND, root["sounds"]); + processPreloadList(AssetType::MODEL, root["models"]); // layouts are loaded automatically } diff --git a/src/assets/AssetsLoader.hpp b/src/assets/AssetsLoader.hpp index 1f30130d..602d841a 100644 --- a/src/assets/AssetsLoader.hpp +++ b/src/assets/AssetsLoader.hpp @@ -12,11 +12,7 @@ #include "interfaces/Task.hpp" #include "typedefs.hpp" #include "Assets.hpp" - -namespace dynamic { - class Map; - class List; -} +#include "data/dv.hpp" class ResPaths; class AssetsLoader; @@ -61,9 +57,9 @@ class AssetsLoader { void tryAddSound(const std::string& name); 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 processPreloadConfigs(const Content* content); public: diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index 35133264..0f69e64e 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -11,7 +11,6 @@ #include "coders/json.hpp" #include "coders/obj.hpp" #include "constants.hpp" -#include "data/dynamic.hpp" #include "debug/Logger.hpp" #include "files/engine_paths.hpp" #include "files/files.hpp" @@ -220,17 +219,17 @@ static void read_anim_file( std::vector>& frameList ) { auto root = files::read_json(animFile); - auto frameArr = root->list("frames"); float frameDuration = DEFAULT_FRAME_DURATION; std::string frameName; - if (frameArr) { - for (size_t i = 0; i < frameArr->size(); i++) { - auto currentFrame = frameArr->list(i); + if (auto found = root.at("frames")) { + auto& frameArr = *found; + for (size_t i = 0; i < frameArr.size(); i++) { + const auto& currentFrame = frameArr[i]; - frameName = currentFrame->str(0); - if (currentFrame->size() > 1) { - frameDuration = currentFrame->integer(1); + frameName = currentFrame[0].asString(); + if (currentFrame.size() > 1) { + frameDuration = currentFrame[1].asNumber(); } frameList.emplace_back(frameName, frameDuration); } diff --git a/src/coders/binary_json.cpp b/src/coders/binary_json.cpp index fd5d2c23..20034c0f 100644 --- a/src/coders/binary_json.cpp +++ b/src/coders/binary_json.cpp @@ -2,38 +2,38 @@ #include -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "byte_utils.hpp" #include "gzip.hpp" +#include "util/Buffer.hpp" using namespace json; -using namespace dynamic; -static void to_binary(ByteBuilder& builder, const Value& value) { - switch (static_cast(value.index())) { - case Type::none: +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 Type::map: { - const auto bytes = to_binary(std::get(value).get()); + case dv::value_type::object: { + const auto bytes = json::to_binary(value); builder.put(bytes.data(), bytes.size()); break; } - case Type::list: + case dv::value_type::list: builder.put(BJSON_TYPE_LIST); - for (const auto& element : std::get(value)->values) { + for (const auto& element : value) { to_binary(builder, element); } builder.put(BJSON_END); break; - case Type::bytes: { - const auto& bytes = std::get(value).get(); + 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()); + builder.putInt32(bytes.size()); + builder.put(bytes.data(), bytes.size()); break; } - case Type::integer: { - auto val = std::get(value); + case dv::value_type::integer: { + auto val = value.asInteger(); if (val >= 0 && val <= 255) { builder.put(BJSON_TYPE_BYTE); builder.put(val); @@ -49,26 +49,23 @@ static void to_binary(ByteBuilder& builder, const Value& value) { } break; } - case Type::number: + case dv::value_type::number: builder.put(BJSON_TYPE_NUMBER); - builder.putFloat64(std::get(value)); + builder.putFloat64(value.asNumber()); break; - case Type::boolean: - builder.put(BJSON_TYPE_FALSE + std::get(value)); + case dv::value_type::boolean: + builder.put(BJSON_TYPE_FALSE + value.asBoolean()); break; - case Type::string: + case dv::value_type::string: builder.put(BJSON_TYPE_STRING); - builder.put(std::get(value)); + builder.put(value.asString()); break; } } -static std::unique_ptr array_from_binary(ByteReader& reader); -static std::unique_ptr object_from_binary(ByteReader& reader); - -std::vector json::to_binary(const Map* obj, bool compress) { +std::vector json::to_binary(const dv::value& object, bool compress) { if (compress) { - auto bytes = to_binary(obj, false); + auto bytes = to_binary(object, false); return gzip::compress(bytes.data(), bytes.size()); } ByteBuilder builder; @@ -78,9 +75,9 @@ std::vector json::to_binary(const Map* obj, bool compress) { builder.putInt32(0); // writing entries - for (auto& entry : obj->values) { - builder.putCStr(entry.first.c_str()); - to_binary(builder, entry.second); + for (const auto& [key, value] : object.asObject()) { + builder.putCStr(key.c_str()); + to_binary(builder, value); } // terminating byte builder.put(BJSON_END); @@ -90,27 +87,23 @@ std::vector json::to_binary(const Map* obj, bool compress) { return builder.build(); } -std::vector json::to_binary(const Value& value, bool compress) { - if (auto map = std::get_if(&value)) { - return to_binary(map->get(), compress); - } - throw std::runtime_error("map is only supported as the root element"); -} +static dv::value list_from_binary(ByteReader& reader); +static dv::value object_from_binary(ByteReader& reader); -static Value value_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 Map_sptr(object_from_binary(reader).release()); + return object_from_binary(reader); case BJSON_TYPE_LIST: - return List_sptr(array_from_binary(reader).release()); + return list_from_binary(reader); case BJSON_TYPE_BYTE: - return static_cast(reader.get()); + return reader.get(); case BJSON_TYPE_INT16: - return static_cast(reader.getInt16()); + return reader.getInt16(); case BJSON_TYPE_INT32: - return static_cast(reader.getInt32()); + return reader.getInt32(); case BJSON_TYPE_INT64: return reader.getInt64(); case BJSON_TYPE_NUMBER: @@ -121,7 +114,7 @@ static Value value_from_binary(ByteReader& reader) { case BJSON_TYPE_STRING: return reader.getString(); case BJSON_TYPE_NULL: - return NONE; + return nullptr; case BJSON_TYPE_BYTES: { int32_t size = reader.getInt32(); if (size < 0) { @@ -132,7 +125,8 @@ static Value value_from_binary(ByteReader& reader) { throw std::runtime_error( "buffer_size > remaining_size "+std::to_string(size)); } - auto bytes = std::make_shared(reader.pointer(), size); + auto bytes = std::make_shared>( + reader.pointer(), size); reader.skip(size); return bytes; } @@ -141,26 +135,26 @@ static Value value_from_binary(ByteReader& reader) { "type support not implemented for <"+std::to_string(typecode)+">"); } -static std::unique_ptr array_from_binary(ByteReader& reader) { - auto array = std::make_unique(); +static dv::value list_from_binary(ByteReader& reader) { + auto list = dv::list(); while (reader.peek() != BJSON_END) { - array->put(value_from_binary(reader)); + list.add(value_from_binary(reader)); } reader.get(); - return array; + return list; } -static std::unique_ptr object_from_binary(ByteReader& reader) { - auto obj = std::make_unique(); +static dv::value object_from_binary(ByteReader& reader) { + auto obj = dv::object(); while (reader.peek() != BJSON_END) { const char* key = reader.getCString(); - obj->put(key, value_from_binary(reader)); + obj[key] = value_from_binary(reader); } reader.get(); return obj; } -std::shared_ptr json::from_binary(const ubyte* src, size_t size) { +dv::value json::from_binary(const ubyte* src, size_t size) { if (size < 2) { throw std::runtime_error("bytes length is less than 2"); } @@ -170,12 +164,6 @@ std::shared_ptr json::from_binary(const ubyte* src, size_t size) { return from_binary(data.data(), data.size()); } else { ByteReader reader(src, size); - Value value = value_from_binary(reader); - - if (auto map = std::get_if(&value)) { - return *map; - } else { - throw std::runtime_error("root value is not an object"); - } + return value_from_binary(reader); } } diff --git a/src/coders/binary_json.hpp b/src/coders/binary_json.hpp index 1a7d9330..c6dc8df1 100644 --- a/src/coders/binary_json.hpp +++ b/src/coders/binary_json.hpp @@ -3,11 +3,9 @@ #include #include -#include "data/dynamic_fwd.hpp" +#include "data/dv.hpp" -namespace dynamic { - class Map; -} +#include "typedefs.hpp" namespace json { inline constexpr int BJSON_END = 0x0; @@ -25,11 +23,7 @@ namespace json { inline constexpr int BJSON_TYPE_NULL = 0xC; inline constexpr int BJSON_TYPE_CDOCUMENT = 0x1F; - std::vector to_binary( - const dynamic::Map* obj, bool compress = false - ); - std::vector to_binary( - const dynamic::Value& obj, bool compress = false - ); - std::shared_ptr from_binary(const ubyte* src, size_t size); + std::vector to_binary(const dv::value& obj, bool compress = false); + + dv::value from_binary(const ubyte* src, size_t size); } diff --git a/src/coders/commons.cpp b/src/coders/commons.cpp index a6406e4d..e915b6a6 100644 --- a/src/coders/commons.cpp +++ b/src/coders/commons.cpp @@ -258,7 +258,7 @@ int64_t BasicParser::parseSimpleInt(int base) { return value; } -dynamic::Value BasicParser::parseNumber() { +dv::value BasicParser::parseNumber() { switch (peek()) { case '-': 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(); int base = 10; if (c == '0' && pos + 1 < source.length() && diff --git a/src/coders/commons.hpp b/src/coders/commons.hpp index 77c8cbf5..e5bb3bc1 100644 --- a/src/coders/commons.hpp +++ b/src/coders/commons.hpp @@ -3,7 +3,7 @@ #include #include -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "typedefs.hpp" inline int is_box(int c) { @@ -90,8 +90,8 @@ protected: void reset(); int64_t parseSimpleInt(int base); - dynamic::Value parseNumber(int sign); - dynamic::Value parseNumber(); + dv::value parseNumber(int sign); + dv::value parseNumber(); std::string parseString(char chr, bool closeRequired = true); parsing_error error(const std::string& message); diff --git a/src/coders/json.cpp b/src/coders/json.cpp index a15a40a2..049eeb40 100644 --- a/src/coders/json.cpp +++ b/src/coders/json.cpp @@ -6,21 +6,19 @@ #include #include -#include "data/dynamic.hpp" #include "util/stringutil.hpp" #include "commons.hpp" using namespace json; -using namespace dynamic; class Parser : BasicParser { - std::unique_ptr parseList(); - std::unique_ptr parseObject(); - dynamic::Value parseValue(); + dv::value parseList(); + dv::value parseObject(); + dv::value parseValue(); public: Parser(std::string_view filename, std::string_view source); - std::unique_ptr parse(); + dv::value parse(); }; inline void newline( @@ -37,15 +35,15 @@ inline void newline( } void stringifyObj( - const Map* obj, + const dv::value& obj, std::stringstream& ss, int indent, const std::string& indentstr, bool nice ); -void stringifyArr( - const List* list, +void stringifyList( + const dv::value& list, std::stringstream& ss, int indent, const std::string& indentstr, @@ -53,56 +51,64 @@ void stringifyArr( ); void stringifyValue( - const Value& value, + const dv::value& value, std::stringstream& ss, int indent, const std::string& indentstr, bool nice ) { - if (auto map = std::get_if(&value)) { - stringifyObj(map->get(), ss, indent, indentstr, nice); - } else if (auto listptr = std::get_if(&value)) { - stringifyArr(listptr->get(), ss, indent, indentstr, nice); - } else if (auto bytesptr = std::get_if(&value)) { - auto bytes = bytesptr->get(); - ss << "\"" << util::base64_encode(bytes->data(), bytes->size()); - ss << "\""; - } else if (auto flag = std::get_if(&value)) { - ss << (*flag ? "true" : "false"); - } else if (auto num = std::get_if(&value)) { - ss << std::setprecision(15) << *num; - } else if (auto num = std::get_if(&value)) { - ss << *num; - } else if (auto str = std::get_if(&value)) { - ss << util::escape(*str); - } else { - ss << "null"; + using dv::value_type; + + switch (value.getType()) { + case value_type::object: + stringifyObj(value, ss, indent, indentstr, nice); + break; + case value_type::list: + stringifyList(value, ss, indent, indentstr, nice); + break; + case value_type::bytes: { + const auto& bytes = value.asBytes(); + ss << "\"" << util::base64_encode(bytes.data(), bytes.size()); + ss << "\""; + break; + } + case value_type::string: + ss << util::escape(value.asString()); + break; + case value_type::number: + ss << std::setprecision(15) << value.asNumber(); + break; + case value_type::integer: + ss << value.asInteger(); + break; + case value_type::boolean: + ss << (value.asBoolean() ? "true" : "false"); + break; + case value_type::none: + ss << "null"; + break; } } -void stringifyArr( - const List* list, +void stringifyList( + const dv::value& list, std::stringstream& ss, int indent, const std::string& indentstr, bool nice ) { - if (list == nullptr) { - ss << "nullptr"; - return; - } - if (list->values.empty()) { + if (list.empty()) { ss << "[]"; return; } ss << "["; - for (size_t i = 0; i < list->size(); i++) { + for (size_t i = 0; i < list.size(); i++) { if (i > 0 || nice) { newline(ss, nice, indent, indentstr); } - const Value& value = list->values[i]; + const auto& value = list[i]; stringifyValue(value, ss, indent + 1, indentstr, nice); - if (i + 1 < list->size()) { + if (i + 1 < list.size()) { ss << ','; } } @@ -113,32 +119,26 @@ void stringifyArr( } void stringifyObj( - const Map* obj, + const dv::value& obj, std::stringstream& ss, int indent, const std::string& indentstr, bool nice ) { - if (obj == nullptr) { - ss << "nullptr"; - return; - } - if (obj->values.empty()) { + if (obj.empty()) { ss << "{}"; return; } ss << "{"; size_t index = 0; - for (auto& entry : obj->values) { - const std::string& key = entry.first; + for (auto& [key, value] : obj.asObject()) { 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()) { + if (index < obj.size()) { ss << ','; } } @@ -149,23 +149,7 @@ void stringifyObj( } 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 + const dv::value& value, bool nice, const std::string& indent ) { std::stringstream ss; stringifyValue(value, ss, 1, indent, nice); @@ -176,7 +160,7 @@ Parser::Parser(std::string_view filename, std::string_view source) : BasicParser(filename, source) { } -std::unique_ptr Parser::parse() { +dv::value Parser::parse() { char next = peek(); if (next != '{') { throw error("'{' expected"); @@ -184,10 +168,9 @@ std::unique_ptr Parser::parse() { return parseObject(); } -std::unique_ptr Parser::parseObject() { +dv::value Parser::parseObject() { expect('{'); - auto obj = std::make_unique(); - auto& map = obj->values; + auto object = dv::object(); while (peek() != '}') { if (peek() == '#') { skipLine(); @@ -199,7 +182,7 @@ std::unique_ptr Parser::parseObject() { throw error("':' expected"); } pos++; - map.insert(std::make_pair(key, parseValue())); + object[key] = parseValue(); next = peek(); if (next == ',') { pos++; @@ -210,19 +193,18 @@ std::unique_ptr Parser::parseObject() { } } pos++; - return obj; + return object; } -std::unique_ptr Parser::parseList() { +dv::value Parser::parseList() { expect('['); - auto arr = std::make_unique(); - auto& values = arr->values; + auto list = dv::list(); while (peek() != ']') { if (peek() == '#') { skipLine(); continue; } - values.push_back(parseValue()); + list.add(parseValue()); char next = peek(); if (next == ',') { @@ -234,13 +216,17 @@ std::unique_ptr Parser::parseList() { } } pos++; - return arr; + return list; } -Value Parser::parseValue() { +dv::value Parser::parseValue() { char next = peek(); if (next == '-' || next == '+' || is_digit(next)) { - return parseNumber(); + auto numeric = parseNumber(); + if (numeric.isInteger()) { + return numeric.asInteger(); + } + return numeric.asNumber(); } if (is_identifier_start(next)) { std::string literal = parseName(); @@ -256,10 +242,10 @@ Value Parser::parseValue() { throw error("invalid literal "); } if (next == '{') { - return Map_sptr(parseObject().release()); + return parseObject(); } if (next == '[') { - return List_sptr(parseList().release()); + return parseList(); } if (next == '"' || next == '\'') { pos++; @@ -268,13 +254,13 @@ Value Parser::parseValue() { throw error("unexpected character '" + std::string({next}) + "'"); } -dynamic::Map_sptr json::parse( +dv::value 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) { +dv::value json::parse(std::string_view source) { return parse("", source); } diff --git a/src/coders/json.hpp b/src/coders/json.hpp index 1491be70..f79b5d46 100644 --- a/src/coders/json.hpp +++ b/src/coders/json.hpp @@ -2,23 +2,15 @@ #include -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "typedefs.hpp" #include "binary_json.hpp" namespace json { - dynamic::Map_sptr parse(std::string_view filename, std::string_view source); - dynamic::Map_sptr parse(std::string_view source); + dv::value parse(std::string_view filename, std::string_view source); + dv::value parse(std::string_view source); 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 + const dv::value& value, bool nice, const std::string& indent=" " ); } diff --git a/src/coders/obj.cpp b/src/coders/obj.cpp index b69ff342..19d82f8c 100644 --- a/src/coders/obj.cpp +++ b/src/coders/obj.cpp @@ -63,18 +63,18 @@ public: } auto cmd = parseName(); if (cmd == "v") { - float x = dynamic::as_number(parseNumber()); - float y = dynamic::as_number(parseNumber()); - float z = dynamic::as_number(parseNumber()); + float x = parseNumber().asNumber(); + float y = parseNumber().asNumber(); + float z = parseNumber().asNumber(); coords.emplace_back(x, y, z); } else if (cmd == "vt") { - float u = dynamic::as_number(parseNumber()); - float v = dynamic::as_number(parseNumber()); + float u = parseNumber().asNumber(); + float v = parseNumber().asNumber(); uvs.emplace_back(u, v); } else if (cmd == "vn") { - float x = dynamic::as_number(parseNumber()); - float y = dynamic::as_number(parseNumber()); - float z = dynamic::as_number(parseNumber()); + float x = parseNumber().asNumber(); + float y = parseNumber().asNumber(); + float z = parseNumber().asNumber(); normals.emplace_back(x, y, z); } else { skipLine(); diff --git a/src/coders/toml.cpp b/src/coders/toml.cpp index 63e13025..9dbf3e6e 100644 --- a/src/coders/toml.cpp +++ b/src/coders/toml.cpp @@ -6,7 +6,6 @@ #include #include -#include "data/dynamic.hpp" #include "data/setting.hpp" #include "files/settings_io.hpp" #include "util/stringutil.hpp" @@ -15,7 +14,7 @@ using namespace toml; class TomlReader : BasicParser { - dynamic::Map_sptr root; + dv::value root; void skipWhitespace() override { 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()) { - return *root; + return root; } size_t offset = 0; - auto& rootMap = *root; + auto rootMap = &root; do { size_t index = section.find('.', offset); if (index == std::string::npos) { - auto map = rootMap.map(section); - if (map == nullptr) { - return rootMap.putMap(section); + auto map = rootMap->at(section); + if (!map) { + return rootMap->object(section); } return *map; } auto subsection = section.substr(offset, index); - auto map = rootMap.map(subsection); - if (map == nullptr) { - rootMap = rootMap.putMap(subsection); + auto map = rootMap->at(subsection); + if (!map) { + rootMap = &rootMap->object(subsection); } else { - rootMap = *map; + rootMap = &*map; } offset = index + 1; } while (true); } - void readSection(const std::string& section, dynamic::Map& map) { + void readSection(const std::string& section, dv::value& map) { while (hasNext()) { skipWhitespace(); if (!hasNext()) { @@ -71,23 +70,23 @@ class TomlReader : BasicParser { expect('='); c = peek(); if (is_digit(c)) { - map.put(name, parseNumber(1)); + map[name] = parseNumber(1); } else if (c == '-' || c == '+') { int sign = c == '-' ? -1 : 1; pos++; - map.put(name, parseNumber(sign)); + map[name] = parseNumber(sign); } else if (is_identifier_start(c)) { std::string identifier = parseName(); if (identifier == "true" || identifier == "false") { - map.put(name, identifier == "true"); + map[name] = identifier == "true"; } else if (identifier == "inf") { - map.put(name, INFINITY); + map[name] = INFINITY; } else if (identifier == "nan") { - map.put(name, NAN); + map[name] = NAN; } } else if (c == '"' || c == '\'') { pos++; - map.put(name, parseString(c)); + map[name] = parseString(c); } else { throw error("feature is not supported"); } @@ -97,36 +96,28 @@ class TomlReader : BasicParser { public: TomlReader(std::string_view file, std::string_view source) : BasicParser(file, source) { - root = dynamic::create_map(); + root = dv::object(); } - dynamic::Map_sptr read() { + dv::value read() { skipWhitespace(); if (!hasNext()) { - return root; + return std::move(root); } - readSection("", *root); - return root; + readSection("", root); + return std::move(root); } }; -dynamic::Map_sptr toml::parse(std::string_view file, std::string_view source) { - return TomlReader(file, source).read(); -} - void toml::parse( SettingsHandler& handler, std::string_view file, std::string_view source ) { auto map = parse(file, source); - for (auto& entry : map->values) { - const auto& sectionName = entry.first; - auto sectionMap = std::get_if(&entry.second); - if (sectionMap == nullptr) { + for (const auto& [sectionName, sectionMap] : map.asObject()) { + if (!sectionMap.isObject()) { continue; } - for (auto& sectionEntry : (*sectionMap)->values) { - const auto& name = sectionEntry.first; - auto& value = sectionEntry.second; + for (const auto& [name, value] : sectionMap.asObject()) { auto fullname = sectionName + "." + name; if (handler.has(fullname)) { 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; if (!name.empty()) { ss << "[" << name << "]\n"; } - for (auto& entry : root.values) { - if (!std::holds_alternative(entry.second)) { - ss << entry.first << " = "; - ss << entry.second << "\n"; + for (const auto& [key, value] : root.asObject()) { + if (!value.isObject()) { + ss << key << " = " << value << "\n"; } } - for (auto& entry : root.values) { - if (auto submap = std::get_if(&entry.second)) { - ss << "\n" - << toml::stringify( - **submap, - name.empty() ? entry.first : name + "." + entry.first - ); + for (const auto& [key, value] : root.asObject()) { + if (value.isObject()) { + ss << "\n" << toml::stringify(value, + name.empty() ? key : name + "." + key); } } return ss.str(); diff --git a/src/coders/toml.hpp b/src/coders/toml.hpp index 669e2279..708c159c 100644 --- a/src/coders/toml.hpp +++ b/src/coders/toml.hpp @@ -2,14 +2,15 @@ #include -#include "data/dynamic.hpp" +#include "data/dv.hpp" class SettingsHandler; namespace toml { std::string stringify(SettingsHandler& handler); - std::string stringify(dynamic::Map& root, const std::string& name = ""); - dynamic::Map_sptr parse(std::string_view file, std::string_view source); + std::string stringify(const dv::value& root, const std::string& name = ""); + + dv::value parse(std::string_view file, std::string_view source); void parse( SettingsHandler& handler, std::string_view file, std::string_view source diff --git a/src/content/Content.hpp b/src/content/Content.hpp index 7622ea7f..9c9c9743 100644 --- a/src/content/Content.hpp +++ b/src/content/Content.hpp @@ -8,8 +8,8 @@ #include #include -#include "data/dynamic_fwd.hpp" #include "content_fwd.hpp" +#include "data/dv.hpp" using DrawGroups = std::set; template @@ -129,18 +129,18 @@ public: class ResourceIndices { std::vector names; std::unordered_map indices; - std::unique_ptr> savedData; + std::unique_ptr> savedData; public: ResourceIndices() - : savedData(std::make_unique>()) { + : savedData(std::make_unique>()) { } 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(); names.push_back(name); - savedData->push_back(map); + savedData->push_back(std::move(map)); } const std::string& getName(size_t index) const { @@ -155,12 +155,12 @@ public: return MISSING; } - dynamic::Map_sptr getSavedData(size_t index) const { + const dv::value& getSavedData(size_t index) const { return savedData->at(index); } - void saveData(size_t index, dynamic::Map_sptr map) const { - savedData->at(index) = map; + void saveData(size_t index, dv::value map) const { + savedData->at(index) = std::move(map); } size_t size() const { diff --git a/src/content/ContentLUT.cpp b/src/content/ContentLUT.cpp index 0ee747bb..48549c16 100644 --- a/src/content/ContentLUT.cpp +++ b/src/content/ContentLUT.cpp @@ -20,9 +20,11 @@ ContentLUT::ContentLUT( template static constexpr size_t get_entries_count( - const ContentUnitIndices& indices, const dynamic::List_sptr& list + const ContentUnitIndices& 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::create( @@ -36,8 +38,8 @@ std::shared_ptr ContentLUT::create( } auto root = files::read_json(filename); - auto blocklist = root->list("blocks"); - auto itemlist = root->list("items"); + auto& blocklist = root["blocks"]; + auto& itemlist = root["items"]; auto* indices = content->getIndices(); size_t blocks_c = get_entries_count(indices->blocks, blocklist); @@ -45,8 +47,8 @@ std::shared_ptr ContentLUT::create( auto lut = std::make_shared(indices, blocks_c, items_c); - lut->blocks.setup(blocklist.get(), content->blocks); - lut->items.setup(itemlist.get(), content->items); + lut->blocks.setup(blocklist, content->blocks); + lut->items.setup(itemlist, content->items); if (lut->hasContentReorder() || lut->hasMissingContent()) { return lut; diff --git a/src/content/ContentLUT.hpp b/src/content/ContentLUT.hpp index cdd4ad72..9e9e0f98 100644 --- a/src/content/ContentLUT.hpp +++ b/src/content/ContentLUT.hpp @@ -6,7 +6,7 @@ #include #include "constants.hpp" -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "typedefs.hpp" #include "Content.hpp" @@ -45,10 +45,10 @@ public: names.emplace_back(""); } } - void setup(dynamic::List* list, const ContentUnitDefs& defs) { - if (list) { - for (size_t i = 0; i < list->size(); i++) { - std::string name = list->str(i); + void setup(const dv::value& list, const ContentUnitDefs& defs) { + if (list != nullptr) { + for (size_t i = 0; i < list.size(); i++) { + const std::string& name = list[i].asString(); if (auto def = defs.find(name)) { set(i, name, def->rt.id); } else { diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index bc8a5f3b..ca4be87d 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -11,7 +11,6 @@ #include "ContentPack.hpp" #include "coders/json.hpp" #include "core_defs.hpp" -#include "data/dynamic.hpp" #include "debug/Logger.hpp" #include "files/files.hpp" #include "items/ItemDef.hpp" @@ -21,6 +20,7 @@ #include "util/listutil.hpp" #include "util/stringutil.hpp" #include "voxels/Block.hpp" +#include "data/dv_util.hpp" namespace fs = std::filesystem; @@ -60,7 +60,7 @@ static void detect_defs( bool ContentLoader::fixPackIndices( const fs::path& folder, - dynamic::Map* indicesRoot, + dv::value& indicesRoot, const std::string& contentSection ) { std::vector detected; @@ -68,25 +68,23 @@ bool ContentLoader::fixPackIndices( std::vector indexed; bool modified = false; - if (!indicesRoot->has(contentSection)) { - indicesRoot->putList(contentSection); + if (!indicesRoot.has(contentSection)) { + indicesRoot.list(contentSection); } - auto arr = indicesRoot->list(contentSection); - if (arr) { - for (uint i = 0; i < arr->size(); i++) { - std::string name = arr->str(i); - if (!util::contains(detected, name)) { - arr->remove(i); - i--; - modified = true; - continue; - } - indexed.push_back(name); + auto& arr = indicesRoot[contentSection]; + for (size_t i = 0; i < arr.size(); i++) { + const std::string& name = arr[i].asString(); + if (!util::contains(detected, name)) { + arr.erase(i); + i--; + modified = true; + continue; } + indexed.push_back(name); } for (auto name : detected) { if (!util::contains(indexed, name)) { - arr->put(name); + arr.add(name); modified = true; } } @@ -100,21 +98,21 @@ void ContentLoader::fixPackIndices() { auto itemsFolder = folder / ContentPack::ITEMS_FOLDER; auto entitiesFolder = folder / ContentPack::ENTITIES_FOLDER; - dynamic::Map_sptr root; + dv::value root; if (fs::is_regular_file(indexFile)) { root = files::read_json(indexFile); } else { - root = dynamic::create_map(); + root = dv::object(); } bool modified = false; - modified |= fixPackIndices(blocksFolder, root.get(), "blocks"); - modified |= fixPackIndices(itemsFolder, root.get(), "items"); - modified |= fixPackIndices(entitiesFolder, root.get(), "entities"); + modified |= fixPackIndices(blocksFolder, root, "blocks"); + modified |= fixPackIndices(itemsFolder, root, "items"); + modified |= fixPackIndices(entitiesFolder, root, "entities"); if (modified) { // 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); - if (root->has("parent")) { - std::string parentName; - root->str("parent", parentName); + if (root.has("parent")) { + const auto& parentName = root["parent"].asString(); auto parentDef = this->builder.blocks.get(parentName); if (parentDef == nullptr) { throw std::runtime_error( @@ -135,29 +132,28 @@ void ContentLoader::loadBlock( parentDef->cloneTo(def); } - root->str("caption", def.caption); + root.at("caption").get(def.caption); // block texturing - if (root->has("texture")) { - std::string texture; - root->str("texture", texture); + if (root.has("texture")) { + const auto& texture = root["texture"].asString(); for (uint i = 0; i < 6; i++) { def.textureFaces[i] = texture; } - } else if (root->has("texture-faces")) { - auto texarr = root->list("texture-faces"); + } else if (root.has("texture-faces")) { + const auto& texarr = root["texture-faces"]; for (uint i = 0; i < 6; i++) { - def.textureFaces[i] = texarr->str(i); + def.textureFaces[i] = texarr[i].asString(); } } // block model std::string modelName; - root->str("model", modelName); + root.at("model").get(modelName); if (auto model = BlockModel_from(modelName)) { if (*model == BlockModel::custom) { - if (root->has("model-primitives")) { - loadCustomBlockModel(def, root->map("model-primitives").get()); + if (root.has("model-primitives")) { + loadCustomBlockModel(def, root["model-primitives"]); } else { logger.error() << name << ": no 'model-primitives' found"; } @@ -168,11 +164,12 @@ void ContentLoader::loadBlock( def.model = BlockModel::none; } - root->str("material", def.material); + root.at("material").get(def.material); // rotation profile std::string profile = "none"; - root->str("rotation", profile); + root.at("rotation").get(profile); + def.rotatable = profile != "none"; if (profile == BlockRotProfile::PIPE_NAME) { def.rotations = BlockRotProfile::PIPE; @@ -184,20 +181,29 @@ void ContentLoader::loadBlock( } // block hitbox AABB [x, y, z, width, height, depth] - auto boxarr = root->list("hitboxes"); - if (boxarr) { - def.hitboxes.resize(boxarr->size()); - for (uint i = 0; i < boxarr->size(); i++) { - auto box = boxarr->list(i); + if (auto found = root.at("hitboxes")) { + const auto& boxarr = *found; + def.hitboxes.resize(boxarr.size()); + for (uint i = 0; i < boxarr.size(); i++) { + const auto& box = boxarr[i]; auto& hitboxesIndex = def.hitboxes[i]; - hitboxesIndex.a = glm::vec3(box->num(0), box->num(1), box->num(2)); - hitboxesIndex.b = glm::vec3(box->num(3), box->num(4), box->num(5)); + hitboxesIndex.a = glm::vec3( + 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; } - } else if ((boxarr = root->list("hitbox"))) { + } else if (auto found = root.at("hitbox")) { + const auto& box = *found; AABB aabb; - aabb.a = glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2)); - aabb.b = glm::vec3(boxarr->num(3), boxarr->num(4), boxarr->num(5)); + aabb.a = glm::vec3( + 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; def.hitboxes = {aabb}; } 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] - if (auto emissionarr = root->list("emission")) { - def.emission[0] = emissionarr->num(0); - def.emission[1] = emissionarr->num(1); - def.emission[2] = emissionarr->num(2); + if (auto found = root.at("emission")) { + const auto& emissionarr = *found; + def.emission[0] = emissionarr[0].asNumber(); + def.emission[1] = emissionarr[1].asNumber(); + def.emission[2] = emissionarr[2].asNumber(); } // block size - if (auto sizearr = root->list("size")) { - def.size.x = sizearr->num(0); - def.size.y = sizearr->num(1); - def.size.z = sizearr->num(2); + if (auto found = root.at("size")) { + const auto& sizearr = *found; + def.size.x = sizearr[0].asNumber(); + def.size.y = sizearr[1].asNumber(); + def.size.z = sizearr[2].asNumber(); if (def.model == BlockModel::block && (def.size.x != 1 || def.size.y != 1 || def.size.z != 1)) { def.model = BlockModel::aabb; @@ -226,22 +234,22 @@ void ContentLoader::loadBlock( } // primitive properties - root->flag("obstacle", def.obstacle); - root->flag("replaceable", def.replaceable); - root->flag("light-passing", def.lightPassing); - root->flag("sky-light-passing", def.skyLightPassing); - root->flag("shadeless", def.shadeless); - root->flag("ambient-occlusion", def.ambientOcclusion); - root->flag("breakable", def.breakable); - root->flag("selectable", def.selectable); - root->flag("grounded", def.grounded); - root->flag("hidden", def.hidden); - root->num("draw-group", def.drawGroup); - root->str("picking-item", def.pickingItem); - root->str("script-name", def.scriptName); - root->str("ui-layout", def.uiLayout); - root->num("inventory-size", def.inventorySize); - root->num("tick-interval", def.tickInterval); + root.at("obstacle").get(def.obstacle); + root.at("replaceable").get(def.replaceable); + root.at("light-passing").get(def.lightPassing); + root.at("sky-light-passing").get(def.skyLightPassing); + root.at("shadeless").get(def.shadeless); + root.at("ambient-occlusion").get(def.ambientOcclusion); + root.at("breakable").get(def.breakable); + root.at("selectable").get(def.selectable); + root.at("grounded").get(def.grounded); + root.at("hidden").get(def.hidden); + root.at("draw-group").get(def.drawGroup); + root.at("picking-item").get(def.pickingItem); + root.at("script-name").get(def.scriptName); + root.at("ui-layout").get(def.uiLayout); + root.at("inventory-size").get(def.inventorySize); + root.at("tick-interval").get(def.tickInterval); if (def.tickInterval == 0) { def.tickInterval = 1; } @@ -251,48 +259,57 @@ void ContentLoader::loadBlock( } } -void ContentLoader::loadCustomBlockModel(Block& def, dynamic::Map* primitives) { - if (primitives->has("aabbs")) { - auto modelboxes = primitives->list("aabbs"); - for (uint i = 0; i < modelboxes->size(); i++) { - /* Parse aabb */ - auto boxarr = modelboxes->list(i); +void ContentLoader::loadCustomBlockModel(Block& def, const dv::value& primitives) { + if (primitives.has("aabbs")) { + const auto& modelboxes = primitives["aabbs"]; + for (uint i = 0; i < modelboxes.size(); i++) { + // Parse aabb + const auto& boxarr = modelboxes[i]; AABB modelbox; - modelbox.a = - glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2)); - modelbox.b = - glm::vec3(boxarr->num(3), boxarr->num(4), boxarr->num(5)); + modelbox.a = glm::vec3( + boxarr[0].asNumber(), boxarr[1].asNumber(), boxarr[2].asNumber() + ); + modelbox.b = glm::vec3( + boxarr[3].asNumber(), boxarr[4].asNumber(), boxarr[5].asNumber() + ); modelbox.b += modelbox.a; def.modelBoxes.push_back(modelbox); - if (boxarr->size() == 7) + if (boxarr.size() == 7) { 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++) { - def.modelTextures.emplace_back(boxarr->str(j)); + def.modelTextures.emplace_back(boxarr[j].asString()); } - else + } else { for (uint j = 6; j < 12; j++) { def.modelTextures.emplace_back("notfound"); } + } } } - if (primitives->has("tetragons")) { - auto modeltetragons = primitives->list("tetragons"); - for (uint i = 0; i < modeltetragons->size(); i++) { - /* Parse tetragon to points */ - auto tgonobj = modeltetragons->list(i); - glm::vec3 p1(tgonobj->num(0), tgonobj->num(1), tgonobj->num(2)), - xw(tgonobj->num(3), tgonobj->num(4), tgonobj->num(5)), - yh(tgonobj->num(6), tgonobj->num(7), tgonobj->num(8)); + if (primitives.has("tetragons")) { + const auto& modeltetragons = primitives["tetragons"]; + for (uint i = 0; i < modeltetragons.size(); i++) { + // Parse tetragon to points + const auto& tgonobj = modeltetragons[i]; + glm::vec3 p1( + tgonobj[0].asNumber(), tgonobj[1].asNumber(), tgonobj[2].asNumber() + ); + 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 + xw); def.modelExtraPoints.push_back(p1 + xw + 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); - if (root->has("parent")) { - std::string parentName; - root->str("parent", parentName); + if (root.has("parent")) { + const auto& parentName = root["parent"].asString(); auto parentDef = this->builder.items.get(parentName); if (parentDef == nullptr) { throw std::runtime_error( @@ -313,11 +329,10 @@ void ContentLoader::loadItem( } parentDef->cloneTo(def); } - - root->str("caption", def.caption); + root.at("caption").get(def.caption); std::string iconTypeStr = ""; - root->str("icon-type", iconTypeStr); + root.at("icon-type").get(iconTypeStr); if (iconTypeStr == "none") { def.iconType = item_icon_type::none; } else if (iconTypeStr == "block") { @@ -327,16 +342,17 @@ void ContentLoader::loadItem( } else if (iconTypeStr.length()) { logger.error() << name << ": unknown icon type" << iconTypeStr; } - root->str("icon", def.icon); - root->str("placing-block", def.placingBlock); - root->str("script-name", def.scriptName); - root->num("stack-size", def.stackSize); + root.at("icon").get(def.icon); + root.at("placing-block").get(def.placingBlock); + root.at("script-name").get(def.scriptName); + root.at("stack-size").get(def.stackSize); // item light emission [r, g, b] where r,g,b in range [0..15] - if (auto emissionarr = root->list("emission")) { - def.emission[0] = emissionarr->num(0); - def.emission[1] = emissionarr->num(1); - def.emission[2] = emissionarr->num(2); + if (auto found = root.at("emission")) { + const auto& emissionarr = *found; + def.emission[0] = emissionarr[0].asNumber(); + 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); - if (root->has("parent")) { - std::string parentName; - root->str("parent", parentName); + if (root.has("parent")) { + const auto& parentName = root["parent"].asString(); auto parentDef = this->builder.entities.get(parentName); if (parentDef == nullptr) { throw std::runtime_error( @@ -357,54 +372,57 @@ void ContentLoader::loadEntity( parentDef->cloneTo(def); } - if (auto componentsarr = root->list("components")) { - for (size_t i = 0; i < componentsarr->size(); i++) { - def.components.emplace_back(componentsarr->str(i)); + if (auto found = root.at("components")) { + for (const auto& elem : *found) { + def.components.emplace_back(elem.asString()); } } - if (auto boxarr = root->list("hitbox")) { - def.hitbox = glm::vec3(boxarr->num(0), boxarr->num(1), boxarr->num(2)); + if (auto found = root.at("hitbox")) { + const auto& arr = *found; + def.hitbox = glm::vec3( + arr[0].asNumber(), arr[1].asNumber(), arr[2].asNumber() + ); } - if (auto sensorsarr = root->list("sensors")) { - for (size_t i = 0; i < sensorsarr->size(); i++) { - if (auto sensorarr = sensorsarr->list(i)) { - auto sensorType = sensorarr->str(0); - if (sensorType == "aabb") { - def.boxSensors.emplace_back( - i, - AABB { - {sensorarr->num(1), - sensorarr->num(2), - sensorarr->num(3)}, - {sensorarr->num(4), - sensorarr->num(5), - sensorarr->num(6)} - } - ); - } else if (sensorType == "radius") { - def.radialSensors.emplace_back(i, sensorarr->num(1)); - } else { - logger.error() - << name << ": sensor #" << i << " - unknown type " - << util::quote(sensorType); - } + if (auto found = root.at("sensors")) { + const auto& arr = *found; + for (size_t i = 0; i < arr.size(); i++) { + const auto& sensorarr = arr[i]; + const auto& sensorType = sensorarr[0].asString(); + if (sensorType == "aabb") { + def.boxSensors.emplace_back( + i, + AABB { + {sensorarr[1].asNumber(), + sensorarr[2].asNumber(), + sensorarr[3].asNumber()}, + {sensorarr[4].asNumber(), + sensorarr[5].asNumber(), + sensorarr[6].asNumber()} + } + ); + } else if (sensorType == "radius") { + def.radialSensors.emplace_back(i, sensorarr[1].asNumber()); + } else { + logger.error() + << name << ": sensor #" << i << " - unknown type " + << util::quote(sensorType); } } } - root->flag("save", def.save.enabled); - root->flag("save-skeleton-pose", def.save.skeleton.pose); - root->flag("save-skeleton-textures", def.save.skeleton.textures); - root->flag("save-body-velocity", def.save.body.velocity); - root->flag("save-body-settings", def.save.body.settings); + root.at("save").get(def.save.enabled); + root.at("save-skeleton-pose").get(def.save.skeleton.pose); + root.at("save-skeleton-textures").get(def.save.skeleton.textures); + root.at("save-body-velocity").get(def.save.body.velocity); + root.at("save-body-settings").get(def.save.body.settings); std::string bodyTypeName; - root->str("body-type", bodyTypeName); + root.at("body-type").get(bodyTypeName); if (auto bodyType = BodyType_from(bodyTypeName)) { def.bodyType = *bodyType; } - root->str("skeleton-name", def.skeletonName); - root->flag("blocking", def.blocking); + root.at("skeleton-name").get(def.skeletonName); + root.at("blocking").get(def.blocking); } void ContentLoader::loadEntity( @@ -482,9 +500,9 @@ void ContentLoader::loadBlockMaterial( BlockMaterial& def, const fs::path& file ) { auto root = files::read_json(file); - root->str("steps-sound", def.stepsSound); - root->str("place-sound", def.placeSound); - root->str("break-sound", def.breakSound); + root.at("steps-sound").get(def.stepsSound); + root.at("place-sound").get(def.placeSound); + root.at("break-sound").get(def.breakSound); } void ContentLoader::load() { @@ -529,7 +547,7 @@ void ContentLoader::load() { std::string parent; if (fs::exists(configFile)) { auto root = files::read_json(configFile); - if (root->has("parent")) root->str("parent", parent); + root.at("parent").get(parent); } return parent; }; @@ -543,9 +561,10 @@ void ContentLoader::load() { return std::make_pair(full, new_name); }; - if (auto blocksarr = root->list("blocks")) { - for (size_t i = 0; i < blocksarr->size(); i++) { - auto [full, name] = processName(blocksarr->str(i)); + if (auto found = root.at("blocks")) { + const auto& blocksarr = *found; + for (size_t i = 0; i < blocksarr.size(); i++) { + auto [full, name] = processName(blocksarr[i].asString()); auto parent = getJsonParent("blocks", name); if (parent.empty() || builder.blocks.get(parent)) { // No dependency or dependency already loaded/exists in another @@ -587,9 +606,10 @@ void ContentLoader::load() { } } - if (auto itemsarr = root->list("items")) { - for (size_t i = 0; i < itemsarr->size(); i++) { - auto [full, name] = processName(itemsarr->str(i)); + if (auto found = root.at("items")) { + const auto& itemsarr = *found; + for (size_t i = 0; i < itemsarr.size(); i++) { + auto [full, name] = processName(itemsarr[i].asString()); auto parent = getJsonParent("items", name); if (parent.empty() || builder.items.get(parent)) { // No dependency or dependency already loaded/exists in another @@ -631,9 +651,10 @@ void ContentLoader::load() { } } - if (auto entitiesarr = root->list("entities")) { - for (size_t i = 0; i < entitiesarr->size(); i++) { - auto [full, name] = processName(entitiesarr->str(i)); + if (auto found = root.at("entities")) { + const auto& entitiesarr = *found; + for (size_t i = 0; i < entitiesarr.size(); i++) { + auto [full, name] = processName(entitiesarr[i].asString()); auto parent = getJsonParent("entities", name); if (parent.empty() || builder.entities.get(parent)) { // No dependency or dependency already loaded/exists in another @@ -716,11 +737,9 @@ void ContentLoader::load() { fs::path resourcesFile = folder / fs::u8path("resources.json"); if (fs::exists(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 arr = resRoot->list(key)) { - loadResources(*resType, arr.get()); - } + loadResources(*resType, arr); } else { logger.warning() << "unknown resource type: " << key; } @@ -728,10 +747,10 @@ void ContentLoader::load() { } } -void ContentLoader::loadResources(ResourceType type, dynamic::List* list) { - for (size_t i = 0; i < list->size(); i++) { +void ContentLoader::loadResources(ResourceType type, const dv::value& list) { + for (size_t i = 0; i < list.size(); i++) { builder.resourceIndices[static_cast(type)].add( - pack->id + ":" + list->str(i), nullptr + pack->id + ":" + list[i].asString(), nullptr ); } } diff --git a/src/content/ContentLoader.hpp b/src/content/ContentLoader.hpp index 01cebae5..fdd93ef8 100644 --- a/src/content/ContentLoader.hpp +++ b/src/content/ContentLoader.hpp @@ -5,6 +5,7 @@ #include #include "content_fwd.hpp" +#include "data/dv.hpp" namespace fs = std::filesystem; @@ -19,11 +20,6 @@ class ContentBuilder; class ContentPackRuntime; struct ContentPackStats; -namespace dynamic { - class Map; - class List; -} - class ContentLoader { const ContentPack* pack; ContentPackRuntime* runtime; @@ -44,7 +40,7 @@ class ContentLoader { GeneratorDef& 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); void loadBlock( Block& def, const std::string& name, const fs::path& file @@ -55,13 +51,13 @@ class ContentLoader { void loadEntity( 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: ContentLoader(ContentPack* pack, ContentBuilder& builder); bool fixPackIndices( const fs::path& folder, - dynamic::Map* indicesRoot, + dv::value& indicesRoot, const std::string& contentSection ); void fixPackIndices(); diff --git a/src/content/ContentPack.cpp b/src/content/ContentPack.cpp index 9bcd8aef..05ee21e9 100644 --- a/src/content/ContentPack.cpp +++ b/src/content/ContentPack.cpp @@ -6,7 +6,7 @@ #include "constants.hpp" #include "coders/json.hpp" -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "files/engine_paths.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) { auto root = files::read_json(folder / fs::path(PACKAGE_FILENAME)); ContentPack pack; - root->str("id", pack.id); - root->str("title", pack.title); - root->str("version", pack.version); - root->str("creator", pack.creator); - root->str("description", pack.description); + root.at("id").get(pack.id); + root.at("title").get(pack.title); + root.at("version").get(pack.version); + root.at("creator").get(pack.creator); + root.at("description").get(pack.description); pack.folder = folder; - - auto dependencies = root->list("dependencies"); - if (dependencies) { - for (size_t i = 0; i < dependencies->size(); i++) { + + if (auto found = root.at("dependencies")) { + const auto& dependencies = *found; + for (const auto& elem : dependencies) { pack.dependencies.push_back( - {DependencyLevel::required, dependencies->str(i)} + {DependencyLevel::required, elem.asString()} ); } } diff --git a/src/data/dv.cpp b/src/data/dv.cpp new file mode 100644 index 00000000..5709fd84 --- /dev/null +++ b/src/data/dv.cpp @@ -0,0 +1,161 @@ +#include "dv.hpp" + +#include + +#include "util/Buffer.hpp" + +namespace dv { + value& value::operator[](const key_t& key) { + check_type(type, value_type::object); + return (*val.object)[key]; + } + const value& value::operator[](const key_t& key) const { + check_type(type, value_type::object); + return (*val.object)[key]; + } + + value& value::operator=(const objects::Bytes& bytes) { + return setBytes(std::make_shared(bytes)); + } + + value& value::operator[](size_t index) { + check_type(type, value_type::list); + return (*val.list)[index]; + } + const value& value::operator[](size_t index) const { + check_type(type, value_type::list); + return (*val.list)[index]; + } + + void value::add(value v) { + check_type(type, value_type::list); + return val.list->push_back(std::move(v)); + } + + value& value::object(const key_t& key) { + reference ref = this->operator[](key); + ref = dv::object(); + return ref; + } + + value& value::list(const key_t& key) { + reference ref = this->operator[](key); + ref = dv::list(); + return ref; + } + + value& value::object() { + check_type(type, value_type::list); + val.list->push_back(std::make_shared()); + return val.list->operator[](val.list->size()-1); + } + + value& value::list() { + check_type(type, value_type::list); + val.list->push_back(std::make_shared()); + return val.list->operator[](val.list->size()-1); + } + + list_t::iterator value::begin() { + check_type(type, value_type::list); + return val.list->begin(); + } + + list_t::iterator value::end() { + check_type(type, value_type::list); + return val.list->end(); + } + + list_t::const_iterator value::begin() const { + check_type(type, value_type::list); + const auto& constlist = *val.list; + return constlist.begin(); + } + + list_t::const_iterator value::end() const { + check_type(type, value_type::list); + const auto& constlist = *val.list; + return constlist.end(); + } + + const std::string& value::asString() const { + check_type(type, value_type::string); + return *val.string; + } + + integer_t value::asInteger() const { + if (type == value_type::integer) { + return val.integer; + } else if (type == value_type::number) { + return static_cast(val.number); + } + throw_type_error(type, value_type::integer); + return 0; // unreachable + } + + number_t value::asNumber() const { + if (type == value_type::number) { + return val.number; + } else if (type == value_type::integer) { + return static_cast(val.integer); + } + throw_type_error(type, value_type::integer); + return 0; // unreachable + } + + boolean_t value::asBoolean() const { + check_type(type, value_type::boolean); + return val.boolean; + } + + objects::Bytes& value::asBytes() { + check_type(type, value_type::bytes); + return *val.bytes; + } + + const objects::Bytes& value::asBytes() const { + check_type(type, value_type::bytes); + return *val.bytes; + } + + const objects::Object& value::asObject() const { + check_type(type, value_type::object); + return *val.object; + } + + size_t value::size() const noexcept { + switch (type) { + case value_type::list: + return val.list->size(); + case value_type::object: + return val.object->size(); + case value_type::string: + return val.string->size(); + default: + 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); +} diff --git a/src/data/dv.hpp b/src/data/dv.hpp new file mode 100644 index 00000000..18a89316 --- /dev/null +++ b/src/data/dv.hpp @@ -0,0 +1,597 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace util { + template class Buffer; +} + +namespace dv { + using integer_t = int64_t; + using number_t = double; + using boolean_t = bool; + using byte_t = unsigned char; + using key_t = std::string; + + enum class value_type : uint8_t { + none = 0, + number, + boolean, + integer, + object, + list, + bytes, + string + }; + + inline const std::string& type_name(value_type type) { + static std::string type_names[] = { + "none", + "number", + "boolean", + "integer", + "object", + "list", + "bytes", + "string" + }; + return type_names[static_cast(type)]; + } + + class value; + + using list_t = std::vector; + using map_t = std::unordered_map; + using pair = std::pair; + + using reference = value&; + using const_reference = const value&; + + namespace objects { + using Object = std::unordered_map; + using List = std::vector; + using Bytes = util::Buffer; + } + + /// @brief nullable value reference returned by value.at(...) + struct optionalvalue { + value* ptr; + + optionalvalue(value* ptr) noexcept : ptr(ptr) {} + + inline operator bool() const noexcept { + return ptr != nullptr; + } + + inline value& operator*() noexcept { + return *ptr; + } + + inline const value& operator*() const noexcept { + return *ptr; + } + + bool get(std::string& dst) const; + bool get(bool& dst) const; + bool get(char& dst) const; + bool get(short& dst) const; + bool get(int& dst) const; + bool get(long& dst) const; + bool get(long long& dst) const; + bool get(unsigned char& dst) const; + bool get(unsigned short& dst) const; + bool get(unsigned int& dst) const; + bool get(unsigned long& dst) const; + bool get(unsigned long long& 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 { + value_type type = value_type::none; + union value_u { + integer_t integer; + number_t number; + boolean_t boolean; + std::unique_ptr string; + std::shared_ptr object; + std::shared_ptr list; + std::shared_ptr bytes; + value_u() noexcept {} + ~value_u() noexcept {} + } val; + + inline value& setBoolean(boolean_t v) noexcept { + this->~value(); + type = value_type::boolean; + val.boolean = v; + return *this; + } + inline value& setInteger(integer_t v) noexcept { + this->~value(); + type = value_type::integer; + val.integer = v; + return *this; + } + inline value& setNumber(number_t v) noexcept { + this->~value(); + type = value_type::number; + val.number = v; + return *this; + } + inline value& setNone() noexcept { + this->~value(); + type = value_type::none; + return *this; + } + inline value& setString(std::string v) noexcept { + this->~value(); + new(&val.string)std::unique_ptr( + std::make_unique(std::move(v))); + type = value_type::string; + return *this; + } + inline value& setString(std::unique_ptr v) noexcept { + this->~value(); + new(&val.string)std::unique_ptr(std::move(v)); + type = value_type::string; + return *this; + } + inline value& setList(std::shared_ptr ptr) noexcept { + this->~value(); + new(&val.list)std::shared_ptr(std::move(ptr)); + type = value_type::list; + return *this; + } + inline value& setObject(std::shared_ptr ptr) noexcept { + this->~value(); + new(&val.object)std::shared_ptr(std::move(ptr)); + type = value_type::object; + return *this; + } + inline value& setBytes(std::shared_ptr ptr) noexcept { + this->~value(); + new(&val.bytes)std::shared_ptr(std::move(ptr)); + type = value_type::bytes; + return *this; + } + public: + value() noexcept : type(value_type::none) {} + + /// @brief Constructor for fundamental types + template + value(T v, std::enable_if_t::value, int> = 0) noexcept { + this->operator=(v); + } + value(std::string v) noexcept { + this->operator=(std::move(v)); + } + value(std::shared_ptr v) noexcept { + this->operator=(std::move(v)); + } + value(std::shared_ptr v) noexcept { + this->operator=(std::move(v)); + } + value(std::shared_ptr v) noexcept { + this->operator=(std::move(v)); + } + + value(const value& v) noexcept : type(value_type::none) { + this->operator=(v); + } + + value(value&& v) noexcept { + this->operator=(std::move(v)); + } + + ~value() noexcept { + switch (type) { + case value_type::object: + val.object.reset(); + break; + case value_type::list: + val.list.reset(); + break; + case value_type::bytes: + val.bytes.reset(); + break; + case value_type::string: + val.string.reset(); + break; + default: + break; + } + } + + inline value& operator=(std::nullptr_t) { + return setNone(); + } + + template + inline std::enable_if_t() && !std::is_same(), value&> + operator=(T v) { + return setInteger(v); + } + + inline value& operator=(float v) { + return setNumber(v); + } + inline value& operator=(double v) { + return setNumber(v); + } + inline value& operator=(bool v) { + return setBoolean(v); + } + inline value& operator=(std::string_view v) { + return setString(std::string(v)); + } + inline value& operator=(std::string v) { + return setString(std::move(v)); + } + inline value& operator=(const char* v) { + return setString(v); + } + inline value& operator=(std::shared_ptr ptr) { + return setList(std::move(ptr)); + } + inline value& operator=(std::shared_ptr ptr) { + return setObject(std::move(ptr)); + } + inline value& operator=(std::shared_ptr ptr) { + return setBytes(std::move(ptr)); + } + value& operator=(const objects::Bytes& bytes); + + inline value& operator=(const value& v) { + switch (v.type) { + case value_type::object: + setObject(v.val.object); + break; + case value_type::list: + setList(v.val.list); + break; + case value_type::bytes: + setBytes(v.val.bytes); + break; + case value_type::string: + setString(*v.val.string); + break; + case value_type::boolean: + setBoolean(v.val.boolean); + break; + case value_type::integer: + setInteger(v.val.integer); + break; + case value_type::number: + setNumber(v.val.number); + break; + case value_type::none: + setNone(); + break; + } + return *this; + } + + inline value& operator=(value&& v) noexcept { + if (type < value_type::object) { + type = v.type; + switch (v.type) { + case value_type::none: + break; + case value_type::integer: + val.integer = v.val.integer; + break; + case value_type::number: + val.number = v.val.number; + break; + case value_type::boolean: + val.boolean = v.val.boolean; + break; + case value_type::string: + new(&val.string)std::unique_ptr( + std::move(v.val.string)); + break; + case value_type::object: + new(&val.object)std::shared_ptr( + std::move(v.val.object)); + break; + case value_type::list: + new(&val.list)std::shared_ptr( + std::move(v.val.list)); + break; + case value_type::bytes: + new(&val.list)std::shared_ptr( + std::move(v.val.bytes)); + break; + } + } else { + switch (v.type) { + case value_type::object: + setObject(std::move(v.val.object)); + break; + case value_type::list: + setList(std::move(v.val.list)); + break; + case value_type::bytes: + setBytes(std::move(v.val.bytes)); + break; + case value_type::string: + setString(std::move(v.val.string)); + break; + case value_type::boolean: + setBoolean(v.val.boolean); + break; + case value_type::integer: + setInteger(v.val.integer); + break; + case value_type::number: + setNumber(v.val.number); + break; + case value_type::none: + setNone(); + break; + } + } + return *this; + } + + void add(value v); + + template + inline void add(T v) { + return add(value(v)); + } + + void erase(const key_t& key); + + void erase(size_t index); + + value& operator[](const key_t& key); + + const value& operator[](const key_t& key) const; + + value& operator[](size_t index); + + 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& list(const key_t& key); + + value& object(); + + value& list(); + + list_t::iterator begin(); + list_t::iterator end(); + + list_t::const_iterator begin() const; + list_t::const_iterator end() const; + + const std::string& asString() const; + + integer_t asInteger() const; + + number_t asNumber() const; + + boolean_t asBoolean() const; + + objects::Bytes& asBytes(); + + const objects::Bytes& asBytes() const; + + const objects::Object& asObject() const; + + inline value_type getType() const { + return type; + } + + std::string asString(std::string def) const { + if (type != value_type::string) { + return def; + } + return *val.string; + } + + 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(val.number); + default: + return def; + } + } + + integer_t asNumber(integer_t def) const { + switch (type) { + case value_type::integer: + return static_cast(val.integer); + case value_type::number: + return val.number; + default: + return def; + } + } + + optionalvalue 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 optionalvalue(nullptr); + } + return optionalvalue(&found->second); + } + + optionalvalue at(size_t index) { + check_type(type, value_type::list); + return optionalvalue(&val.list->at(index)); + } + + const optionalvalue at(size_t index) const { + check_type(type, value_type::list); + return optionalvalue(&val.list->at(index)); + } + + bool has(const key_t& k) const; + + size_t size() const noexcept; + + size_t length() const noexcept { + return size(); + } + inline bool empty() const noexcept { + return size() == 0; + } + + inline bool isString() const noexcept { + return type == value_type::string; + } + inline bool isObject() const noexcept { + return type == value_type::object; + } + inline bool isList() const noexcept { + return type == value_type::list; + } + inline bool isInteger() const noexcept { + return type == value_type::integer; + } + inline bool isNumber() const noexcept { + return type == value_type::number; + } + }; + + inline bool is_numeric(const value& val) { + return val.isInteger() && val.isNumber(); + } +} + +namespace dv { + inline const std::string& type_name(const value& value) { + return type_name(value.getType()); + } + + inline value object() { + return std::make_shared(); + } + + inline value list() { + return std::make_shared(); + } + + inline value list(std::initializer_list values) { + return std::make_shared(values); + } + + template inline bool get_to_int(value* ptr, T& dst) { + if (ptr) { + dst = ptr->asInteger(); + return true; + } + return false; + } + template inline bool get_to_num(value* ptr, T& dst) { + if (ptr) { + dst = ptr->asNumber(); + return true; + } + return false; + } + inline bool optionalvalue::get(std::string& dst) const { + if (ptr) { + dst = ptr->asString(); + return true; + } + return false; + } + + inline bool optionalvalue::get(bool& dst) const { + if (ptr) { + dst = ptr->asBoolean(); + return true; + } + return false; + } + + inline bool optionalvalue::get(char& dst) const { + return get_to_int(ptr, dst); + } + inline bool optionalvalue::get(short& dst) const { + return get_to_int(ptr, dst); + } + inline bool optionalvalue::get(int& dst) const { + return get_to_int(ptr, dst); + } + inline bool optionalvalue::get(long& dst) const { + return get_to_int(ptr, dst); + } + inline bool optionalvalue::get(long long& dst) const { + return get_to_int(ptr, dst); + } + inline bool optionalvalue::get(unsigned char& dst) const { + return get_to_int(ptr, dst); + } + inline bool optionalvalue::get(unsigned short& dst) const { + return get_to_int(ptr, dst); + } + inline bool optionalvalue::get(unsigned int& dst) const { + return get_to_int(ptr, dst); + } + inline bool optionalvalue::get(unsigned long& dst) const { + return get_to_int(ptr, dst); + } + inline bool optionalvalue::get(unsigned long long& dst) const { + return get_to_int(ptr, dst); + } + inline bool optionalvalue::get(float& dst) const { + return get_to_num(ptr, dst); + } + inline bool optionalvalue::get(double& dst) const { + return get_to_num(ptr, dst); + } +} + +std::ostream& operator<<(std::ostream& stream, const dv::value& value); diff --git a/src/data/dv_util.hpp b/src/data/dv_util.hpp new file mode 100644 index 00000000..e016edb0 --- /dev/null +++ b/src/data/dv_util.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include "dv.hpp" + +#include + +namespace dv { + template + inline dv::value to_value(glm::vec vec) { + auto list = dv::list(); + for (size_t i = 0; i < n; i++) { + list.add(vec[i]); + } + return list; + } + + template + inline dv::value to_value(glm::mat 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 + void get_vec(const dv::value& list, glm::vec& vec) { + for (size_t i = 0; i < n; i++) { + vec[i] = list[i].asNumber(); + } + } + + template + void get_vec(const dv::value& map, const std::string& key, glm::vec& vec) { + if (!map.has(key)) { + return; + } + auto& list = map[key]; + for (size_t i = 0; i < n; i++) { + if constexpr (std::is_floating_point()) { + vec[i] = list[i].asNumber(); + } else { + vec[i] = list[i].asInteger(); + } + } + } + + template + void get_mat( + const dv::value& list, + glm::mat& 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 + void get_mat( + const dv::value& map, + const std::string& key, + glm::mat& 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(); + } + } + } +} diff --git a/src/data/dynamic.cpp b/src/data/dynamic.cpp deleted file mode 100644 index ea363fec..00000000 --- a/src/data/dynamic.cpp +++ /dev/null @@ -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(value.index())) { - case Type::string: - return std::get(value); - case Type::boolean: - return std::get(value) ? "true" : "false"; - case Type::number: - return std::to_string(std::get(value)); - case Type::integer: - return std::to_string(std::get(value)); - default: - throw std::runtime_error("type error"); - } -} - -number_t List::num(size_t index) const { - const auto& value = values[index]; - switch (static_cast(value.index())) { - case Type::number: - return std::get(value); - case Type::integer: - return std::get(value); - case Type::string: - return std::stoll(std::get(value)); - case Type::boolean: - return std::get(value); - default: - throw std::runtime_error("type error"); - } -} - -integer_t List::integer(size_t index) const { - const auto& value = values[index]; - switch (static_cast(value.index())) { - case Type::number: - return std::get(value); - case Type::integer: - return std::get(value); - case Type::string: - return std::stoll(std::get(value)); - case Type::boolean: - return std::get(value); - default: - throw std::runtime_error("type error"); - } -} - -const Map_sptr& List::map(size_t index) const { - if (auto* val = std::get_if(&values[index])) { - return *val; - } else { - throw std::runtime_error("type error"); - } -} - -List* List::list(size_t index) const { - if (auto* val = std::get_if(&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(value.index())) { - case Type::integer: - return std::get(value); - case Type::boolean: - return std::get(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(value.index())) { - case Type::string: - return std::get(value); - case Type::boolean: - return std::get(value) ? "true" : "false"; - case Type::number: - return std::to_string(std::get(value)); - case Type::integer: - return std::to_string(std::get(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(value.index())) { - case Type::number: - return std::get(value); - case Type::integer: - return std::get(value); - case Type::string: - return std::stoull(std::get(value)); - case Type::boolean: - return std::get(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(value.index())) { - case Type::number: - return std::get(value); - case Type::integer: - return std::get(value); - case Type::string: - return std::stoull(std::get(value)); - case Type::boolean: - return std::get(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(value.index())) { - case Type::integer: - return std::get(value); - case Type::boolean: - return std::get(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(dst)); -} - -void Map::num(const std::string& key, ubyte& dst) const { - dst = get(key, static_cast(dst)); -} - -void Map::num(const std::string& key, int& dst) const { - dst = get(key, static_cast(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(dst)); -} - -void Map::num(const std::string& key, uint& dst) const { - dst = get(key, static_cast(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(&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(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(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 values) { - return std::make_shared(values); -} - -Map_sptr dynamic::create_map( - std::initializer_list> entries -) { - return std::make_shared(entries); -} - -ByteBuffer_sptr dynamic::create_bytes(size_t size) { - return std::make_shared(size); -} - -number_t dynamic::get_number(const Value& value) { - if (auto num = std::get_if(&value)) { - return *num; - } else if (auto num = std::get_if(&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(&value)) { - return *num; - } - throw std::runtime_error("cannot cast " + type_name(value) + " to integer"); -} diff --git a/src/data/dynamic.hpp b/src/data/dynamic.hpp deleted file mode 100644 index 193b224d..00000000 --- a/src/data/dynamic.hpp +++ /dev/null @@ -1,190 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#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 values = {}); - Map_sptr create_map( - std::initializer_list> 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(value) || - std::holds_alternative(value); - } - - inline number_t as_number(const Value& value) { - if (auto num = std::get_if(&value)) { - return *num; - } else if (auto num = std::get_if(&value)) { - return *num; - } - return NAN; - } - - class List { - public: - std::vector values; - - List() = default; - List(std::vector 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 value) { - return put(Map_sptr(std::move(value))); - } - List& put(std::unique_ptr value) { - return put(List_sptr(std::move(value))); - } - List& put(std::unique_ptr 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 values; - - Map() = default; - Map(std::unordered_map values) - : values(std::move(values)) {}; - - template - 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(def)); - } - uint get(const std::string& key, uint def) const { - return get(key, static_cast(def)); - } - uint64_t get(const std::string& key, uint64_t def) const { - return get(key, static_cast(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 value) { - return put(key, Map_sptr(value.release())); - } - Map& put(std::string key, std::unique_ptr value) { - return put(key, List_sptr(value.release())); - } - Map& put(std::string key, int value) { - return put(key, Value(static_cast(value))); - } - Map& put(std::string key, unsigned int value) { - return put(key, Value(static_cast(value))); - } - Map& put(std::string key, int64_t value) { - return put(key, Value(static_cast(value))); - } - Map& put(std::string key, uint64_t value) { - return put(key, Value(static_cast(value))); - } - Map& put(std::string key, float value) { - return put(key, Value(static_cast(value))); - } - Map& put(std::string key, double value) { - return put(key, Value(static_cast(value))); - } - Map& put(std::string key, bool value) { - return put(key, Value(static_cast(value))); - } - Map& put(const std::string& key, const ByteBuffer* bytes) { - return put(key, std::make_unique( - bytes->data(), bytes->size())); - } - Map& put(std::string key, const ubyte* bytes, size_t size) { - return put(key, std::make_unique(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); diff --git a/src/data/dynamic_fwd.hpp b/src/data/dynamic_fwd.hpp deleted file mode 100644 index c4f8eb87..00000000 --- a/src/data/dynamic_fwd.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "typedefs.hpp" -#include "util/Buffer.hpp" - -namespace dynamic { - class Map; - class List; - - using ByteBuffer = util::Buffer; - using Map_sptr = std::shared_ptr; - using List_sptr = std::shared_ptr; - using ByteBuffer_sptr = std::shared_ptr; - - 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; -} diff --git a/src/data/dynamic_util.hpp b/src/data/dynamic_util.hpp deleted file mode 100644 index ff389086..00000000 --- a/src/data/dynamic_util.hpp +++ /dev/null @@ -1,113 +0,0 @@ -#pragma once - -#include - -#include "dynamic.hpp" - -namespace dynamic { - template - inline dynamic::List_sptr to_value(glm::vec vec) { - auto list = dynamic::create_list(); - for (size_t i = 0; i < n; i++) { - list->put(vec[i]); - } - return list; - } - - template - inline dynamic::List_sptr to_value(glm::vec vec) { - auto list = dynamic::create_list(); - for (size_t i = 0; i < n; i++) { - list->put(static_cast(vec[i])); - } - return list; - } - - template - inline dynamic::List_sptr to_value(glm::mat 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 - void get_vec( - const dynamic::Map_sptr& root, - const std::string& name, - glm::vec& vec - ) { - if (const auto& list = root->list(name)) { - for (size_t i = 0; i < n; i++) { - vec[i] = list->num(i); - } - } - } - - /// TODO: remove raw pointer overloads - template - void get_vec( - const dynamic::Map* root, - const std::string& name, - glm::vec& vec - ) { - if (const auto& list = root->list(name)) { - for (size_t i = 0; i < n; i++) { - vec[i] = list->integer(i); - } - } - } - - template - void get_vec( - const dynamic::List_sptr& root, size_t index, glm::vec& vec - ) { - if (const auto& list = root->list(index)) { - for (size_t i = 0; i < n; i++) { - vec[i] = list->num(i); - } - } - } - - template - void get_vec( - const dynamic::List_sptr& root, size_t index, glm::vec& vec - ) { - if (const auto& list = root->list(index)) { - for (size_t i = 0; i < n; i++) { - vec[i] = list->integer(i); - } - } - } - - template - void get_mat( - const dynamic::Map_sptr& root, - const std::string& name, - glm::mat& 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 - void get_mat( - const dynamic::List_sptr& root, size_t index, glm::mat& 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); - } - } - } - } -} diff --git a/src/files/WorldConverter.cpp b/src/files/WorldConverter.cpp index 8e23e432..306b1a1a 100644 --- a/src/files/WorldConverter.cpp +++ b/src/files/WorldConverter.cpp @@ -6,7 +6,6 @@ #include #include "content/ContentLUT.hpp" -#include "data/dynamic.hpp" #include "debug/Logger.hpp" #include "files/files.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 { logger.info() << "converting player " << file.u8string(); auto map = files::read_json(file); - Player::convert(map.get(), lut.get()); - files::write_json(file, map.get()); + Player::convert(map, lut.get()); + files::write_json(file, map); } void WorldConverter::convert(const convert_task& task) const { diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index 562c40c0..70eb1752 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -13,7 +13,6 @@ #include "constants.hpp" #include "content/Content.hpp" #include "core_defs.hpp" -#include "data/dynamic.hpp" #include "debug/Logger.hpp" #include "items/Inventory.hpp" #include "items/ItemDef.hpp" @@ -101,23 +100,23 @@ void WorldFiles::writePacks(const std::vector& packs) { template static void write_indices( - const ContentUnitIndices& indices, dynamic::List& list + const ContentUnitIndices& indices, dv::value& list ) { for (auto unit : indices.getIterable()) { - list.put(unit->name); + list.add(unit->name); } } void WorldFiles::writeIndices(const ContentIndices* indices) { - dynamic::Map root; - write_indices(indices->blocks, root.putList("blocks")); - write_indices(indices->items, root.putList("items")); - write_indices(indices->entities, root.putList("entities")); - files::write_json(getIndicesFile(), &root); + dv::value root = dv::object(); + write_indices(indices->blocks, root.list("blocks")); + write_indices(indices->items, root.list("items")); + write_indices(indices->entities, root.list("entities")); + files::write_json(getIndicesFile(), root); } void WorldFiles::writeWorldInfo(const WorldInfo& info) { - files::write_json(getWorldFile(), info.serialize().get()); + files::write_json(getWorldFile(), info.serialize()); } std::optional WorldFiles::readWorldInfo() { @@ -128,23 +127,22 @@ std::optional WorldFiles::readWorldInfo() { } auto root = files::read_json(file); WorldInfo info {}; - info.deserialize(root.get()); + info.deserialize(root); return info; } 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); - for (size_t i = 0; i < list->size(); i++) { - auto map = list->map(i); - std::string name; - map->str("name", name); + for (size_t i = 0; i < list.size(); i++) { + auto& map = list[i]; + const auto& name = map["name"].asString(); size_t index = indices.indexOf(name); if (index == ResourceIndices::MISSING) { logger.warning() << "discard " << name; } else { - indices.saveData(index, map->map("saved")); + indices.saveData(index, map["saved"]); } } } @@ -156,11 +154,9 @@ bool WorldFiles::readResourcesData(const Content* content) { return false; } 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 arr = root->list(key)) { - read_resources_data(content, arr, *resType); - } + read_resources_data(content, arr, *resType); } else { logger.warning() << "unknown resource type: " << key; } @@ -168,31 +164,29 @@ bool WorldFiles::readResourcesData(const Content* content) { 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 blocks = root->list("blocks"); - for (uint i = 0; i < blocks->size(); i++) { - auto name = blocks->str(i); + auto& blocks = root["blocks"]; + for (uint i = 0; i < blocks.size(); i++) { + auto name = blocks[i].asString(); if (name.find(prefix) != 0) continue; - auto value = blocks->getValueWriteable(i); - *value = CORE_AIR; + blocks[i] = CORE_AIR; } - auto items = root->list("items"); - for (uint i = 0; i < items->size(); i++) { - auto name = items->str(i); + auto& items = root["items"]; + for (uint i = 0; i < items.size(); i++) { + auto& name = items[i].asString(); if (name.find(prefix) != 0) continue; - auto value = items->getValueWriteable(i); - *value = CORE_EMPTY; + items[i] = CORE_EMPTY; } } void WorldFiles::removeIndices(const std::vector& packs) { auto root = files::read_json(getIndicesFile()); 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 { diff --git a/src/files/WorldRegions.cpp b/src/files/WorldRegions.cpp index bd97a1e7..4fb13499 100644 --- a/src/files/WorldRegions.cpp +++ b/src/files/WorldRegions.cpp @@ -7,10 +7,10 @@ #include "coders/json.hpp" #include "coders/byte_utils.hpp" #include "coders/rle.hpp" -#include "data/dynamic.hpp" #include "items/Inventory.hpp" #include "maths/voxmaths.hpp" #include "util/data_io.hpp" +#include "coders/binary_json.hpp" #define REGION_FORMAT_MAGIC ".VOXREG" @@ -365,7 +365,7 @@ static std::unique_ptr write_inventories( for (auto& entry : inventories) { builder.putInt32(entry.first); 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.put(bytes.data(), bytes.size()); } @@ -468,20 +468,20 @@ chunk_inventories_map WorldRegions::fetchInventories(int x, int z) { auto map = json::from_binary(reader.pointer(), size); reader.skip(size); auto inv = std::make_shared(0, 0); - inv->deserialize(map.get()); + inv->deserialize(map); meta[index] = inv; } return meta; } -dynamic::Map_sptr WorldRegions::fetchEntities(int x, int z) { +dv::value WorldRegions::fetchEntities(int x, int z) { uint32_t bytesSize; const ubyte* data = getData(x, z, REGION_LAYER_ENTITIES, bytesSize); if (data == nullptr) { return nullptr; } auto map = json::from_binary(data, bytesSize); - if (map->size() == 0) { + if (map.size() == 0) { return nullptr; } return map; diff --git a/src/files/WorldRegions.hpp b/src/files/WorldRegions.hpp index e346dddc..9923ee05 100644 --- a/src/files/WorldRegions.hpp +++ b/src/files/WorldRegions.hpp @@ -8,7 +8,6 @@ #include #include -#include "data/dynamic_fwd.hpp" #include "typedefs.hpp" #include "util/BufferPool.hpp" #include "voxels/Chunk.hpp" @@ -198,7 +197,7 @@ public: std::unique_ptr getChunk(int x, int z); std::unique_ptr getLights(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); diff --git a/src/files/files.cpp b/src/files/files.cpp index e0e52297..c1f74c63 100644 --- a/src/files/files.cpp +++ b/src/files/files.cpp @@ -11,7 +11,6 @@ #include "coders/gzip.hpp" #include "coders/json.hpp" #include "coders/toml.hpp" -#include "data/dynamic.hpp" #include "util/stringutil.hpp" namespace fs = std::filesystem; @@ -116,30 +115,30 @@ bool files::write_string(const fs::path& filename, const std::string content) { } 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, " ")); } 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); return files::write_bytes(filename, bytes.data(), bytes.size()); } -std::shared_ptr files::read_json(const fs::path& filename) { +dv::value files::read_json(const fs::path& filename) { std::string text = files::read_string(filename); return json::parse(filename.string(), text); } -std::shared_ptr files::read_binary_json(const fs::path& file) { +dv::value files::read_binary_json(const fs::path& file) { size_t size; - std::unique_ptr bytes(files::read_bytes(file, size)); + auto bytes = files::read_bytes(file, size); return json::from_binary(bytes.get(), size); } -std::shared_ptr 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)); } diff --git a/src/files/files.hpp b/src/files/files.hpp index abcbdbb4..d6827dae 100644 --- a/src/files/files.hpp +++ b/src/files/files.hpp @@ -7,13 +7,10 @@ #include #include "typedefs.hpp" +#include "data/dv.hpp" namespace fs = std::filesystem; -namespace dynamic { - class Map; -} - namespace files { /// @brief Read-only random access file class rafile { @@ -46,7 +43,7 @@ namespace files { /// @param nice if true, human readable format will be used, otherwise /// minimal 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 @@ -54,7 +51,7 @@ namespace files { /// @param compressed use gzip compression bool write_binary_json( const fs::path& filename, - const dynamic::Map* obj, + const dv::value& obj, bool compressed = false ); @@ -65,8 +62,8 @@ namespace files { /// @brief Read JSON or BJSON file /// @param file *.json or *.bjson file - std::shared_ptr read_json(const fs::path& file); - std::shared_ptr read_binary_json(const fs::path& file); - std::shared_ptr read_toml(const fs::path& file); + dv::value read_json(const fs::path& file); + dv::value read_binary_json(const fs::path& file); + dv::value read_toml(const fs::path& file); std::vector read_list(const fs::path& file); } diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp index b9993f15..f5fc05d2 100644 --- a/src/files/settings_io.cpp +++ b/src/files/settings_io.cpp @@ -80,12 +80,13 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) { 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); if (found == map.end()) { throw std::runtime_error("setting '" + name + "' does not exist"); } auto setting = found->second; + if (auto number = dynamic_cast(setting)) { return static_cast(number->get()); } else if (auto integer = dynamic_cast(setting)) { @@ -121,20 +122,26 @@ bool SettingsHandler::has(const std::string& name) const { } template -static void set_numeric_value(T* setting, const dynamic::Value& value) { - if (auto num = std::get_if(&value)) { - setting->set(*num); - } else if (auto num = std::get_if(&value)) { - setting->set(*num); - } else if (auto flag = std::get_if(&value)) { - setting->set(*flag); - } else { - throw std::runtime_error("type error, numeric value expected"); +static void set_numeric_value(T* setting, const dv::value& value) { + using dv::value_type; + + switch (value.getType()) { + case value_type::integer: + setting->set(value.asInteger()); + break; + case value_type::number: + 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( - const std::string& name, const dynamic::Value& value + const std::string& name, const dv::value& value ) { auto found = map.find(name); if (found == map.end()) { @@ -148,16 +155,23 @@ void SettingsHandler::setValue( } else if (auto flag = dynamic_cast(setting)) { set_numeric_value(flag, value); } else if (auto string = dynamic_cast(setting)) { - if (auto num = std::get_if(&value)) { - string->set(std::to_string(*num)); - } else if (auto num = std::get_if(&value)) { - string->set(std::to_string(*num)); - } else if (auto flag = std::get_if(&value)) { - string->set(*flag ? "true" : "false"); - } else if (auto str = std::get_if(&value)) { - string->set(*str); - } else { - throw std::runtime_error("not implemented for type"); + using dv::value_type; + + switch (value.getType()) { + case value_type::integer: + string->set(std::to_string(value.asInteger())); + break; + case value_type::number: + string->set(std::to_string(value.asNumber())); + break; + 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 { throw std::runtime_error( diff --git a/src/files/settings_io.hpp b/src/files/settings_io.hpp index 00d3eb76..b5d17df6 100644 --- a/src/files/settings_io.hpp +++ b/src/files/settings_io.hpp @@ -5,7 +5,7 @@ #include #include -#include "data/dynamic.hpp" +#include "data/dv.hpp" class Setting; struct EngineSettings; @@ -21,8 +21,8 @@ class SettingsHandler { public: SettingsHandler(EngineSettings& settings); - dynamic::Value getValue(const std::string& name) const; - void setValue(const std::string& name, const dynamic::Value& value); + dv::value getValue(const std::string& name) const; + void setValue(const std::string& name, const dv::value& value); std::string toString(const std::string& name) const; Setting* getSetting(const std::string& name) const; bool has(const std::string& name) const; diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 178563ac..925627e7 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -403,14 +403,12 @@ void Hud::closeInventory() { } void Hud::add(const HudElement& element) { - using namespace dynamic; - gui->add(element.getNode()); auto document = element.getDocument(); if (document) { auto invview = std::dynamic_pointer_cast(element.getNode()); auto inventory = invview ? invview->getInventory() : nullptr; - std::vector args; + std::vector args; args.emplace_back(inventory ? inventory.get()->getId() : 0); for (int i = 0; i < 3; i++) { args.emplace_back(static_cast(blockPos[i])); diff --git a/src/frontend/locale.cpp b/src/frontend/locale.cpp index 1ce866b2..de040a11 100644 --- a/src/frontend/locale.cpp +++ b/src/frontend/locale.cpp @@ -7,7 +7,7 @@ #include "content/ContentPack.hpp" #include "files/files.hpp" #include "util/stringutil.hpp" -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "debug/Logger.hpp" 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); langs::locales_info.clear(); - root->str("fallback", fallback); + root.at("fallback").get(fallback); - auto langs = root->map("langs"); - if (langs) { + if (auto found = root.at("langs")) { + auto& langs = *found; auto logline = logger.info(); logline << "locales "; - for (auto& entry : langs->values) { - auto langInfo = entry.second; - + for (const auto& [key, langInfo] : langs.asObject()) { std::string name; - if (auto mapptr = std::get_if(&langInfo)) { - name = (*mapptr)->get("name", "none"s); + if (langInfo.isObject()) { + name = langInfo["name"].asString("none"); } else { continue; } - logline << "[" << entry.first << " (" << name << ")] "; - langs::locales_info[entry.first] = LocaleInfo {entry.first, name}; + logline << "[" << key << " (" << name << ")] "; + langs::locales_info[key] = LocaleInfo {key, name}; } logline << "added"; } diff --git a/src/frontend/menu.cpp b/src/frontend/menu.cpp index 9769a2b5..7955fad5 100644 --- a/src/frontend/menu.cpp +++ b/src/frontend/menu.cpp @@ -6,7 +6,7 @@ #include "delegates.hpp" #include "engine.hpp" -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "interfaces/Task.hpp" #include "files/engine_paths.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) { return [=](const std::string& query) { - using namespace dynamic; - - std::vector args; + std::vector args; std::string name; 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); name = query.substr(0, index); - auto map = create_map(); + auto map = dv::object(); auto filename = "query for "+name; BasicParser parser(filename, argstr); while (parser.hasNext()) { auto key = std::string(parser.readUntil('=')); parser.nextChar(); auto value = std::string(parser.readUntil('&')); - map->put(key, value); + map[key] = value; } args.emplace_back(map); } else { @@ -106,7 +104,7 @@ bool menus::call(Engine* engine, runnable func) { } } -UiDocument* menus::show(Engine* engine, const std::string& name, std::vector args) { +UiDocument* menus::show(Engine* engine, const std::string& name, std::vector args) { auto menu = engine->getGUI()->getMenu(); auto file = engine->getResPaths()->find("layouts/"+name+".xml"); auto fullname = "core:layouts/"+name; @@ -123,8 +121,6 @@ UiDocument* menus::show(Engine* engine, const std::string& name, std::vector& task, const std::wstring& text) { - using namespace dynamic; - uint initialWork = task->getWorkTotal(); auto menu = engine->getGUI()->getMenu(); diff --git a/src/frontend/menu.hpp b/src/frontend/menu.hpp index f4e70db2..7a527c4d 100644 --- a/src/frontend/menu.hpp +++ b/src/frontend/menu.hpp @@ -1,6 +1,6 @@ #pragma once -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "graphics/ui/elements/Menu.hpp" #include @@ -21,7 +21,7 @@ namespace menus { UiDocument* show( Engine* engine, const std::string& name, - std::vector args + std::vector args ); void show_process_panel(Engine* engine, const std::shared_ptr& task, const std::wstring& text=L""); diff --git a/src/graphics/ui/elements/TrackBar.hpp b/src/graphics/ui/elements/TrackBar.hpp index 3d9cbfe9..b80b41ac 100644 --- a/src/graphics/ui/elements/TrackBar.hpp +++ b/src/graphics/ui/elements/TrackBar.hpp @@ -1,7 +1,6 @@ #pragma once #include "UINode.hpp" -#include "data/dynamic_fwd.hpp" namespace gui { class TrackBar : public UINode { diff --git a/src/interfaces/Serializable.hpp b/src/interfaces/Serializable.hpp index 881f599e..24457d44 100644 --- a/src/interfaces/Serializable.hpp +++ b/src/interfaces/Serializable.hpp @@ -1,12 +1,12 @@ #pragma once -#include "data/dynamic_fwd.hpp" +#include "data/dv.hpp" #include class Serializable { public: - virtual ~Serializable() { } - virtual std::unique_ptr serialize() const = 0; - virtual void deserialize(dynamic::Map* src) = 0; + virtual ~Serializable() {} + virtual dv::value serialize() const = 0; + virtual void deserialize(const dv::value& src) = 0; }; diff --git a/src/items/Inventory.cpp b/src/items/Inventory.cpp index 34f20bba..4611c19d 100644 --- a/src/items/Inventory.cpp +++ b/src/items/Inventory.cpp @@ -1,7 +1,6 @@ #include "Inventory.hpp" #include "content/ContentLUT.hpp" -#include "data/dynamic.hpp" 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) { - id = src->get("id", 1); - auto slotsarr = src->list("slots"); - size_t slotscount = slotsarr->size(); +void Inventory::deserialize(const dv::value& src) { + id = src["id"].asInteger(1); + auto& slotsarr = src["slots"]; + size_t slotscount = slotsarr.size(); while (slots.size() < slotscount) { slots.emplace_back(); } for (size_t i = 0; i < slotscount; i++) { - auto item = slotsarr->map(i); - itemid_t id = item->get("id", ITEM_EMPTY); - itemcount_t count = item->get("count", 0); + auto& item = slotsarr[i]; + itemid_t id = item["id"].asInteger(); + itemcount_t count = 0; + if (item.has("count")){ + count = item["count"].asInteger(); + } auto& slot = slots[i]; slot.set(ItemStack(id, count)); } } -std::unique_ptr Inventory::serialize() const { - auto map = std::make_unique(); - map->put("id", id); +dv::value Inventory::serialize() const { + auto map = dv::object(); + map["id"] = id; + auto& slotsarr = map.list("slots"); - auto& slotsarr = map->putList("slots"); for (size_t i = 0; i < slots.size(); i++) { auto& item = slots[i]; itemid_t id = item.getItemId(); itemcount_t count = item.getCount(); - auto& slotmap = slotsarr.putMap(); - slotmap.put("id", id); + auto& slotmap = slotsarr.object(); + slotmap["id"] = id; if (count) { - slotmap.put("count", count); + slotmap["count"] = count; } } return map; } -void Inventory::convert(dynamic::Map* data, const ContentLUT* lut) { - auto slotsarr = data->list("slots"); - for (size_t i = 0; i < slotsarr->size(); i++) { - auto item = slotsarr->map(i); - itemid_t id = item->get("id", ITEM_EMPTY); +void Inventory::convert(dv::value& data, const ContentLUT* lut) { + auto& slotsarr = data["slots"]; + for (auto& item : data["slots"]) { + itemid_t id = item["id"].asInteger(ITEM_EMPTY); itemid_t replacement = lut->items.getId(id); - item->put("id", replacement); - if (replacement == 0 && item->has("count")) { - item->remove("count"); + item["id"] = replacement; + if (replacement == 0 && item.has("count")) { + item.erase("count"); } } } diff --git a/src/items/Inventory.hpp b/src/items/Inventory.hpp index a557d2c0..2ec3ea0b 100644 --- a/src/items/Inventory.hpp +++ b/src/items/Inventory.hpp @@ -7,10 +7,6 @@ #include "typedefs.hpp" #include "ItemStack.hpp" -namespace dynamic { - class Map; -} - class ContentLUT; class ContentIndices; @@ -37,12 +33,11 @@ public: size_t end = -1 ); - /* deserializing inventory */ - void deserialize(dynamic::Map* src) override; - /* serializing inventory */ - std::unique_ptr serialize() const override; + void deserialize(const dv::value& src) 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) { this->id = id; diff --git a/src/logic/CommandsInterpreter.cpp b/src/logic/CommandsInterpreter.cpp index ffe5d22e..d2e5bb03 100644 --- a/src/logic/CommandsInterpreter.cpp +++ b/src/logic/CommandsInterpreter.cpp @@ -59,7 +59,7 @@ public: } } - dynamic::Value parseValue() { + dv::value parseValue() { char c = peek(); if (is_cmd_identifier_start(c) || c == '@') { auto str = parseIdentifier(true); @@ -68,7 +68,7 @@ public: } else if (str == "false") { return false; } else if (str == "none" || str == "nil" || str == "null") { - return dynamic::NONE; + return nullptr; } return str; } @@ -116,8 +116,8 @@ public: enumname = parseEnum(); } bool optional = false; - dynamic::Value def {}; - dynamic::Value origin {}; + dv::value def; + dv::value origin; bool loop = true; while (hasNext() && loop) { char c = peek(); @@ -136,7 +136,13 @@ public: break; } } - return Argument {name, type, optional, def, origin, enumname}; + return Argument { + std::move(name), + type, + optional, + std::move(def), + std::move(origin), + std::move(enumname)}; } Command parseScheme(executor_func executor, std::string_view description) { @@ -173,18 +179,17 @@ public: inline parsing_error typeError( const std::string& argname, const std::string& expected, - const dynamic::Value& value + const dv::value& value ) { return argumentError( - argname, expected + " expected, got " + dynamic::type_name(value) + argname, expected + " expected, got " + dv::type_name(value) ); } - template 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(value)) { + if (value.getType() != type) { if (arg->optional) { return false; } else { @@ -194,10 +199,11 @@ public: return true; } - inline bool selectorCheck(Argument* arg, const dynamic::Value& value) { - if (auto string = std::get_if(&value)) { - if ((*string)[0] == '@') { - if (!util::is_integer((*string).substr(1))) { + inline bool selectorCheck(Argument* arg, const dv::value& value) { + if (value.isString()) { + const auto& string = value.asString(); + if (string[0] == '@') { + if (!util::is_integer(string.substr(1))) { throw argumentError(arg->name, "invalid selector"); } return true; @@ -210,12 +216,13 @@ public: } } - bool typeCheck(Argument* arg, const dynamic::Value& value) { + bool typeCheck(Argument* arg, const dv::value& value) { switch (arg->type) { case ArgType::enumvalue: { - if (auto* string = std::get_if(&value)) { + if (value.getType() == dv::value_type::string) { + const auto& string = value.asString(); auto& enumname = arg->enumname; - if (enumname.find("|" + *string + "|") == + if (enumname.find("|" + string + "|") == std::string::npos) { throw error( "argument " + util::quote(arg->name) + @@ -231,7 +238,7 @@ public: break; } case ArgType::number: - if (!dynamic::is_numeric(value)) { + if (!dv::is_numeric(value)) { if (arg->optional) { return false; } else { @@ -242,9 +249,9 @@ public: case ArgType::selector: return selectorCheck(arg, value); case ArgType::integer: - return typeCheck(arg, value, "integer"); + return typeCheck(arg, dv::value_type::integer, value, "integer"); case ArgType::string: - if (!std::holds_alternative(value)) { + if (!value.isString()) { return !arg->optional; } break; @@ -252,36 +259,35 @@ public: return true; } - dynamic::Value fetchOrigin( + dv::value fetchOrigin( CommandsInterpreter* interpreter, Argument* arg ) { - if (dynamic::is_numeric(arg->origin)) { - return arg->origin; - } else if (auto string = std::get_if(&arg->origin)) { - return (*interpreter)[*string]; + if (dv::is_numeric(arg->origin)) { + return dv::value(arg->origin); + } else if (arg->origin.getType() == dv::value_type::string) { + return dv::value((*interpreter)[arg->origin.asString()]); } - return dynamic::NONE; + return nullptr; } - dynamic::Value applyRelative( - Argument* arg, dynamic::Value value, const dynamic::Value& origin + dv::value applyRelative( + Argument* arg, dv::value value, const dv::value& origin ) { - if (origin.index() == 0) { + if (origin == nullptr) { return value; } try { if (arg->type == ArgType::number) { - return dynamic::get_number(origin) + dynamic::get_number(value); + return origin.asNumber() + value.asNumber(); } else { - return dynamic::get_integer(origin) + - dynamic::get_integer(value); + return origin.asInteger() + value.asInteger(); } } catch (std::runtime_error& err) { throw argumentError(arg->name, err.what()); } } - dynamic::Value parseRelativeValue( + dv::value parseRelativeValue( CommandsInterpreter* interpreter, Argument* arg ) { if (arg->type != ArgType::number && arg->type != ArgType::integer) { @@ -293,13 +299,13 @@ public: return origin; } auto value = parseValue(); - if (origin.index() == 0) { + if (origin == nullptr) { return value; } - return applyRelative(arg, value, origin); + return applyRelative(arg, std::move(value), origin); } - inline dynamic::Value performKeywordArg( + inline dv::value performKeywordArg( CommandsInterpreter* interpreter, Command* command, const std::string& key @@ -322,14 +328,14 @@ public: if (command == nullptr) { throw error("unknown command " + util::quote(name)); } - auto args = dynamic::create_list(); - auto kwargs = dynamic::create_map(); + auto args = dv::list(); + auto kwargs = dv::object(); int arg_index = 0; while (hasNext()) { bool relative = false; - dynamic::Value value = dynamic::NONE; + dv::value value; if (peek() == '~') { relative = true; value = static_cast(0); @@ -338,18 +344,17 @@ public: if (hasNext() && peekNoJump() != ' ') { value = parseValue(); - if (auto string = std::get_if(&value)) { - if ((*string)[0] == '$') { - value = (*interpreter)[string->substr(1)]; + if (value.isString()) { + const auto& string = value.asString(); + if (string[0] == '$') { + value = (*interpreter)[string.substr(1)]; } } // keyword argument - if (!relative && hasNext() && peek() == '=') { - auto key = std::get(value); - kwargs->put( - key, performKeywordArg(interpreter, command, key) - ); + if (value.isString() && !relative && hasNext() && peek() == '=') { + const auto& key = value.asString(); + kwargs[key] = performKeywordArg(interpreter, command, key); } } @@ -357,46 +362,48 @@ public: Argument* arg = nullptr; do { if (arg) { - if (auto string = std::get_if(&arg->def)) { - if ((*string)[0] == '$') { - args->put((*interpreter)[string->substr(1)]); + if (arg->def.isString()) { + const auto& string = arg->def.asString(); + if (string[0] == '$') { + args.add((*interpreter)[string.substr(1)]); } else { - args->put(arg->def); + args.add(arg->def); } } else { - args->put(arg->def); + args.add(arg->def); } } arg = command->getArgument(arg_index++); if (arg == nullptr) { throw error("extra positional argument"); } - if (arg->origin.index() && relative) { + if (arg->origin != nullptr && relative) { break; } } while (!typeCheck(arg, value)); if (relative) { value = - applyRelative(arg, value, fetchOrigin(interpreter, arg)); + applyRelative(arg, std::move(value), fetchOrigin(interpreter, arg)); } - args->put(value); + args.add(std::move(value)); } while (auto arg = command->getArgument(arg_index++)) { if (!arg->optional) { throw error("missing argument " + util::quote(arg->name)); } else { - if (auto string = std::get_if(&arg->def)) { - if ((*string)[0] == '$') { - args->put((*interpreter)[string->substr(1)]); + if (arg->def.isString()) { + const auto& string = arg->def.asString(); + if (string[0] == '$') { + args.add((*interpreter)[string.substr(1)]); continue; } } - args->put(arg->def); + args.add(arg->def); } } - return Prompt {command, args, kwargs}; + return Prompt {command, std::move(args), std::move(kwargs)}; } }; diff --git a/src/logic/CommandsInterpreter.hpp b/src/logic/CommandsInterpreter.hpp index 11144720..af3e54ac 100644 --- a/src/logic/CommandsInterpreter.hpp +++ b/src/logic/CommandsInterpreter.hpp @@ -5,7 +5,7 @@ #include #include -#include "data/dynamic.hpp" +#include "data/dv.hpp" namespace cmd { enum class ArgType { number, integer, enumvalue, selector, string }; @@ -31,8 +31,8 @@ namespace cmd { std::string name; ArgType type; bool optional; - dynamic::Value def; - dynamic::Value origin; + dv::value def; + dv::value origin; std::string enumname; }; @@ -41,12 +41,12 @@ namespace cmd { struct Prompt { Command* command; - dynamic::List_sptr args; // positional arguments list - dynamic::Map_sptr kwargs; // keyword arguments table + dv::value args; // positional arguments list + dv::value kwargs; // keyword arguments table }; - using executor_func = std::function; class Command { @@ -85,7 +85,7 @@ namespace cmd { return &found->second; } - dynamic::Value execute( + dv::value execute( CommandsInterpreter* interpreter, const Prompt& prompt ) { return executor(interpreter, prompt.args, prompt.kwargs); @@ -127,7 +127,7 @@ namespace cmd { class CommandsInterpreter { std::unique_ptr repository; - std::unordered_map variables; + std::unordered_map variables; public: CommandsInterpreter() : repository(std::make_unique()) { @@ -141,15 +141,15 @@ namespace cmd { Prompt parse(std::string_view text); - dynamic::Value execute(std::string_view input) { + dv::value execute(std::string_view input) { return execute(parse(input)); } - dynamic::Value execute(const Prompt& prompt) { + dv::value execute(const Prompt& prompt) { return prompt.command->execute(this, prompt); } - dynamic::Value& operator[](const std::string& name) { + dv::value& operator[](const std::string& name) { return variables[name]; } diff --git a/src/logic/EngineController.cpp b/src/logic/EngineController.cpp index 6ce12ee8..7545a5b9 100644 --- a/src/logic/EngineController.cpp +++ b/src/logic/EngineController.cpp @@ -88,16 +88,15 @@ void show_convert_request( static void show_content_missing( Engine* engine, const std::shared_ptr& lut ) { - using namespace dynamic; - auto root = create_map(); - auto& contentEntries = root->putList("content"); + auto root = dv::object(); + auto& contentEntries = root.list("content"); for (auto& entry : lut->getMissingContent()) { std::string contentName = ContentType_name(entry.type); - auto& contentEntry = contentEntries.putMap(); - contentEntry.put("type", contentName); - contentEntry.put("name", entry.name); + auto& contentEntry = contentEntries.object(); + contentEntry["type"] = contentName; + contentEntry["name"] = entry.name; } - menus::show(engine, "reports/missing_content", {root}); + menus::show(engine, "reports/missing_content", {std::move(root)}); } static bool loadWorldContent(Engine* engine, const fs::path& folder) { diff --git a/src/logic/scripting/lua/libentity.cpp b/src/logic/scripting/lua/libentity.cpp index e4c49c8f..845e4e96 100644 --- a/src/logic/scripting/lua/libentity.cpp +++ b/src/logic/scripting/lua/libentity.cpp @@ -50,14 +50,11 @@ static int l_spawn(lua::State* L) { auto defname = lua::tostring(L, 1); auto& def = content->entities.require(defname); auto pos = lua::tovec3(L, 2); - dynamic::Map_sptr args = nullptr; + dv::value args = nullptr; if (lua::gettop(L) > 2) { - auto value = lua::tovalue(L, 3); - if (auto map = std::get_if(&value)) { - args = *map; - } + args = lua::tovalue(L, 3); } - level->entities->spawn(def, pos, args); + level->entities->spawn(def, pos, std::move(args)); return 1; } diff --git a/src/logic/scripting/lua/libgeneration.cpp b/src/logic/scripting/lua/libgeneration.cpp index b7c6eff7..956c28e5 100644 --- a/src/logic/scripting/lua/libgeneration.cpp +++ b/src/logic/scripting/lua/libgeneration.cpp @@ -20,7 +20,7 @@ static int l_save_structure(lua::State* L) { auto structure = VoxelStructure::create(level, pointA, pointB, saveEntities); auto map = structure->serialize(); - auto bytes = json::to_binary(map.get()); + auto bytes = json::to_binary(map); files::write_bytes(fs::u8path(filename), bytes.data(), bytes.size()); return 0; } diff --git a/src/logic/scripting/lua/libjson.cpp b/src/logic/scripting/lua/libjson.cpp index a0e394f5..da0bec38 100644 --- a/src/logic/scripting/lua/libjson.cpp +++ b/src/logic/scripting/lua/libjson.cpp @@ -1,17 +1,12 @@ #include "coders/json.hpp" -#include "data/dynamic.hpp" #include "api_lua.hpp" static int l_json_stringify(lua::State* L) { auto value = lua::tovalue(L, 1); - if (auto mapptr = std::get_if(&value)) { - bool nice = lua::toboolean(L, 2); - auto string = json::stringify(mapptr->get(), nice, " "); - return lua::pushstring(L, string); - } else { - throw std::runtime_error("table expected"); - } + bool nice = lua::toboolean(L, 2); + auto string = json::stringify(value, nice, " "); + return lua::pushstring(L, string); } static int l_json_parse(lua::State* L) { diff --git a/src/logic/scripting/lua/libtoml.cpp b/src/logic/scripting/lua/libtoml.cpp index 6aa2e1a7..4a5cb1bf 100644 --- a/src/logic/scripting/lua/libtoml.cpp +++ b/src/logic/scripting/lua/libtoml.cpp @@ -1,5 +1,4 @@ #include "coders/toml.hpp" -#include "data/dynamic.hpp" #include "api_lua.hpp" using namespace scripting; @@ -7,8 +6,8 @@ using namespace scripting; static int l_toml_stringify(lua::State* L) { auto value = lua::tovalue(L, 1); - if (auto mapptr = std::get_if(&value)) { - auto string = toml::stringify(**mapptr); + if (value.isObject()) { + auto string = toml::stringify(value); return lua::pushstring(L, string); } else { 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) { auto string = lua::require_string(L, 1); auto element = toml::parse("", string); - auto value = std::make_unique(element); - return lua::pushvalue(L, *value); + return lua::pushvalue(L, element); } const luaL_Reg tomllib[] = { diff --git a/src/logic/scripting/lua/lua_engine.hpp b/src/logic/scripting/lua/lua_engine.hpp index 1a36fab5..1690fbbd 100644 --- a/src/logic/scripting/lua/lua_engine.hpp +++ b/src/logic/scripting/lua/lua_engine.hpp @@ -3,7 +3,6 @@ #include #include -#include "data/dynamic.hpp" #include "delegates.hpp" #include "logic/scripting/scripting_functional.hpp" #include "lua_util.hpp" diff --git a/src/logic/scripting/lua/lua_util.cpp b/src/logic/scripting/lua/lua_util.cpp index a6b934aa..09e6dca1 100644 --- a/src/logic/scripting/lua/lua_util.cpp +++ b/src/logic/scripting/lua/lua_util.cpp @@ -22,33 +22,42 @@ std::string lua::env_name(int env) { return "_ENV" + util::mangleid(env); } -int lua::pushvalue(State* L, const dynamic::Value& value) { - using namespace dynamic; +int lua::pushvalue(State* L, const dv::value& value) { + using dv::value_type; - if (auto* flag = std::get_if(&value)) { - pushboolean(L, *flag); - } else if (auto* num = std::get_if(&value)) { - pushinteger(L, *num); - } else if (auto* num = std::get_if(&value)) { - pushnumber(L, *num); - } else if (auto* str = std::get_if(&value)) { - pushstring(L, *str); - } else if (auto listptr = std::get_if(&value)) { - auto list = *listptr; - createtable(L, list->size(), 0); - for (size_t i = 0; i < list->size(); i++) { - pushvalue(L, list->get(i)); - rawseti(L, i + 1); + switch (value.getType()) { + case value_type::none: + pushnil(L); + break; + case value_type::boolean: + pushboolean(L, value.asBoolean()); + break; + case value_type::number: + pushnumber(L, value.asNumber()); + break; + case value_type::integer: + pushinteger(L, value.asInteger()); + break; + 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(&value)) { - auto map = *mapptr; - createtable(L, 0, map->size()); - for (auto& entry : map->values) { - pushvalue(L, entry.second); - setfield(L, entry.first); + case value_type::object: { + createtable(L, 0, value.size()); + for (const auto& [key, elem] : value.asObject()) { + pushvalue(L, elem); + setfield(L, key); + } } - } else { - pushnil(L); } return 1; } @@ -61,13 +70,13 @@ int lua::pushwstring(State* L, const std::wstring& str) { return pushstring(L, util::wstr2str_utf8(str)); } -dynamic::Value lua::tovalue(State* L, int idx) { - using namespace dynamic; +dv::value lua::tovalue(State* L, int idx) { + using dv::value_type; auto type = lua::type(L, idx); switch (type) { case LUA_TNIL: case LUA_TNONE: - return dynamic::NONE; + return nullptr; case LUA_TBOOLEAN: return toboolean(L, idx) == 1; case LUA_TNUMBER: { @@ -91,22 +100,22 @@ dynamic::Value lua::tovalue(State* L, int idx) { int len = objlen(L, idx); if (len) { // array - auto list = create_list(); + auto list = dv::list(); for (int i = 1; i <= len; i++) { rawgeti(L, i, idx); - list->put(tovalue(L, -1)); + list.add(tovalue(L, -1)); pop(L); } return list; } else { // table - auto map = create_map(); + auto map = dv::object(); pushvalue(L, idx); pushnil(L); while (next(L, -2)) { pushvalue(L, -2); auto key = tostring(L, -1); - map->put(key, tovalue(L, -2)); + map[key] = tovalue(L, -2); pop(L, 2); } pop(L); @@ -219,7 +228,7 @@ runnable lua::create_runnable(State* L) { scripting::common_func lua::create_lambda(State* L) { auto funcptr = create_lambda_handler(L); - return [=](const std::vector& args) { + return [=](const std::vector& args) -> dv::value { getglobal(L, LAMBDAS_TABLE); getfield(L, *funcptr); for (const auto& arg : args) { @@ -230,7 +239,7 @@ scripting::common_func lua::create_lambda(State* L) { pop(L); return result; } - return dynamic::Value(dynamic::NONE); + return nullptr; }; } diff --git a/src/logic/scripting/lua/lua_util.hpp b/src/logic/scripting/lua/lua_util.hpp index bd9df34c..fc202555 100644 --- a/src/logic/scripting/lua/lua_util.hpp +++ b/src/logic/scripting/lua/lua_util.hpp @@ -4,6 +4,7 @@ #include #include +#include "data/dv.hpp" #include "lua_wrapper.hpp" #include "lua_custom_types.hpp" #define GLM_ENABLE_EXPERIMENTAL @@ -401,10 +402,10 @@ namespace lua { 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); [[nodiscard]] - 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) { lua_getfield(L, idx, name.c_str()); diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index d8bf0d51..412bd403 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -345,7 +345,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 ) { auto L = lua::get_main_thread(); @@ -353,15 +353,15 @@ dynamic::Value scripting::get_component_value( if (lua::getfield(L, name)) { return lua::tovalue(L, -1); } - return dynamic::NONE; + return nullptr; } void scripting::on_entity_spawn( const EntityDef&, entityid_t eid, const std::vector>& components, - dynamic::Map_sptr args, - dynamic::Map_sptr saved + const dv::value& args, + const dv::value& saved ) { auto L = lua::get_main_thread(); lua::requireglobal(L, STDCOMP); @@ -384,8 +384,8 @@ void scripting::on_entity_spawn( if (args != nullptr) { std::string compfieldname = component->name; util::replaceAll(compfieldname, ":", "__"); - if (auto datamap = args->map(compfieldname)) { - lua::pushvalue(L, datamap); + if (args.has(compfieldname)) { + lua::pushvalue(L, args[compfieldname]); } else { lua::createtable(L, 0, 0); } @@ -397,8 +397,8 @@ void scripting::on_entity_spawn( if (saved == nullptr) { lua::createtable(L, 0, 0); } else { - if (auto datamap = saved->map(component->name)) { - lua::pushvalue(L, datamap); + if (saved.has(component->name)) { + lua::pushvalue(L, saved[component->name]); } else { lua::createtable(L, 0, 0); } @@ -579,10 +579,10 @@ void scripting::on_entities_render(float delta) { } void scripting::on_ui_open( - UiDocument* layout, std::vector args + UiDocument* layout, std::vector args ) { auto argsptr = - std::make_shared>(std::move(args)); + std::make_shared>(std::move(args)); std::string name = layout->getId() + ".open"; lua::emit_event(lua::get_main_thread(), name, [=](auto L) { for (const auto& value : *argsptr) { diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index 85fd8323..3f4ada53 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -6,7 +6,7 @@ #include #include -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "delegates.hpp" #include "typedefs.hpp" #include "scripting_functional.hpp" @@ -89,15 +89,15 @@ namespace scripting { 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 ); void on_entity_spawn( const EntityDef& def, entityid_t eid, const std::vector>& components, - dynamic::Map_sptr args, - dynamic::Map_sptr saved + const dv::value& args, + const dv::value& saved ); void on_entity_despawn(const Entity& entity); void on_entity_grounded(const Entity& entity, float force); @@ -113,7 +113,7 @@ namespace scripting { void on_entity_used(const Entity& entity, Player* player); /// @brief Called on UI view show - void on_ui_open(UiDocument* layout, std::vector args); + void on_ui_open(UiDocument* layout, std::vector args); void on_ui_progress(UiDocument* layout, int workDone, int totalWork); diff --git a/src/logic/scripting/scripting_functional.cpp b/src/logic/scripting/scripting_functional.cpp index 30c31b54..02398b49 100644 --- a/src/logic/scripting/scripting_functional.cpp +++ b/src/logic/scripting/scripting_functional.cpp @@ -160,7 +160,7 @@ vec2supplier scripting::create_vec2_supplier( }; } -dynamic::to_string_func scripting::create_tostring( +value_to_string_func scripting::create_tostring( const scriptenv& env, const std::string& src, const std::string& file ) { auto L = lua::get_main_thread(); @@ -168,7 +168,7 @@ dynamic::to_string_func scripting::create_tostring( lua::loadbuffer(L, *env, src, file); lua::call(L, 0, 1); auto func = lua::create_lambda(L); - return [func](const dynamic::Value& value) { + return [func](const dv::value& value) { auto result = func({value}); return json::stringify(result, true, " "); }; diff --git a/src/logic/scripting/scripting_functional.hpp b/src/logic/scripting/scripting_functional.hpp index e1d40040..2b962dee 100644 --- a/src/logic/scripting/scripting_functional.hpp +++ b/src/logic/scripting/scripting_functional.hpp @@ -3,13 +3,13 @@ #include #include -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "delegates.hpp" #include "typedefs.hpp" namespace scripting { - using common_func = - std::function&)>; + using common_func = std::function&)>; + using value_to_string_func = std::function; runnable create_runnable( const scriptenv& env, @@ -71,7 +71,7 @@ namespace scripting { const std::string& file = "" ); - dynamic::to_string_func create_tostring( + value_to_string_func create_tostring( const scriptenv& env, const std::string& src, const std::string& file = "" diff --git a/src/logic/scripting/scripting_world_generation.cpp b/src/logic/scripting/scripting_world_generation.cpp index 29ab2cc8..a296de22 100644 --- a/src/logic/scripting/scripting_world_generation.cpp +++ b/src/logic/scripting/scripting_world_generation.cpp @@ -10,7 +10,7 @@ #include "content/Content.hpp" #include "voxels/Block.hpp" #include "voxels/Chunk.hpp" -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "world/generator/GeneratorDef.hpp" class LuaGeneratorScript : public GeneratorScript { @@ -105,11 +105,12 @@ public: }; static BlocksLayer load_layer( - const dynamic::Map_sptr& map, uint& lastLayersHeight, bool& hasResizeableLayer + const dv::value& map, uint& lastLayersHeight, bool& hasResizeableLayer ) { - auto name = map->get("block"); - int height = map->get("height"); - bool belowSeaLevel = map->get("below_sea_level", true); + const auto& name = map["block"].asString(); + int height = map["height"].asInteger(); + bool belowSeaLevel = true; + map.at("below_sea_level").get(belowSeaLevel); if (hasResizeableLayer) { lastLayersHeight += height; @@ -124,14 +125,14 @@ static BlocksLayer load_layer( } static inline BlocksLayers load_layers( - const dynamic::List_sptr& layersArr, const std::string& fieldname + const dv::value& layersArr, const std::string& fieldname ) { uint lastLayersHeight = 0; bool hasResizeableLayer = false; std::vector layers; - for (int i = 0; i < layersArr->size(); i++) { - const auto& layerMap = layersArr->map(i); + for (int i = 0; i < layersArr.size(); i++) { + const auto& layerMap = layersArr[i]; try { layers.push_back( load_layer(layerMap, lastLayersHeight, hasResizeableLayer)); @@ -144,18 +145,18 @@ static inline BlocksLayers load_layers( } static inline BiomePlants load_plants( - const dynamic::Map_sptr& biomeMap + const dv::value& biomeMap ) { - float plantChance = biomeMap->get("plant_chance", 0.0); + float plantChance = 0.0f; + biomeMap.at("plant_chance").get(plantChance); float plantsWeightSum = 0.0f; std::vector plants; - if (biomeMap->has("plants")) { - auto plantsArr = biomeMap->list("plants"); - for (size_t i = 0; i < plantsArr->size(); i++) { - auto entry = plantsArr->map(i); - auto block = entry->get("block"); - float weight = entry->get("weight"); + if (biomeMap.has("plants")) { + const auto& plantsArr = biomeMap["plants"]; + for (const auto& entry : plantsArr) { + const auto& block = entry["block"].asString(); + float weight = entry["weight"].asNumber(); if (weight <= 0.0f) { throw std::runtime_error("weight must be positive"); } @@ -169,28 +170,28 @@ static inline BiomePlants load_plants( } static inline Biome load_biome( - const dynamic::Map_sptr& biomeMap, + const dv::value& biomeMap, const std::string& name, uint parametersCount, int idx ) { std::vector parameters; - const auto& paramsArr = biomeMap->list("parameters"); - if (paramsArr->size() < parametersCount) { + const auto& paramsArr = biomeMap["parameters"]; + if (paramsArr.size() < parametersCount) { throw std::runtime_error( std::to_string(parametersCount)+" parameters expected"); } for (size_t i = 0; i < parametersCount; i++) { - const auto& paramMap = paramsArr->map(i); - float value = paramMap->get("value"); - float weight = paramMap->get("weight"); + const auto& paramMap = paramsArr[i]; + float value = paramMap["value"].asNumber(); + float weight = paramMap["weight"].asNumber(); parameters.push_back(BiomeParameter {value, weight}); } BiomePlants plants = load_plants(biomeMap); - BlocksLayers groundLayers = load_layers(biomeMap->list("layers"), "layers"); - BlocksLayers seaLayers = load_layers(biomeMap->list("sea_layers"), "sea_layers"); + BlocksLayers groundLayers = load_layers(biomeMap["layers"], "layers"); + BlocksLayers seaLayers = load_layers(biomeMap["sea_layers"], "sea_layers"); return Biome { name, std::move(parameters), @@ -209,19 +210,16 @@ std::unique_ptr scripting::load_generator( lua::pop(L, load_script(*env, "generator", file)); lua::pushenv(L, *env); - auto val = lua::tovalue(L, -1); + auto root = lua::tovalue(L, -1); lua::pop(L); - - auto root = std::get(val); - uint biomeParameters = root->get("biome_parameters"); - uint seaLevel = root->get("sea_level"); + uint biomeParameters = root["biome_parameters"].asInteger(); + uint seaLevel = root["sea_level"].asInteger(); std::vector biomes; - const auto& biomesMap = root->map("biomes"); - for (const auto& [biomeName, value] : biomesMap->values) { - const auto& biomeMap = std::get(value); + const auto& biomesMap = root["biomes"]; + for (const auto& [biomeName, biomeMap] : biomesMap.asObject()) { try { biomes.push_back( load_biome(biomeMap, biomeName, biomeParameters, -2)); diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index b50b4318..7726ce5c 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -5,7 +5,7 @@ #include "assets/Assets.hpp" #include "content/Content.hpp" -#include "data/dynamic_util.hpp" +#include "data/dv_util.hpp" #include "debug/Logger.hpp" #include "engine.hpp" #include "graphics/core/DrawContext.hpp" @@ -113,8 +113,8 @@ static void initialize_body( entityid_t Entities::spawn( const EntityDef& def, glm::vec3 position, - dynamic::Map_sptr args, - dynamic::Map_sptr saved, + dv::value args, + dv::value saved, entityid_t uid ) { auto skeleton = level->content->getSkeleton(def.skeletonName); @@ -166,15 +166,14 @@ entityid_t Entities::spawn( ); scripting.components.emplace_back(std::move(component)); } - dynamic::Map_sptr componentsMap = nullptr; - if (saved) { - componentsMap = saved->map("comps"); + dv::value componentsMap = nullptr; + if (saved != nullptr) { + componentsMap = saved["comps"]; loadEntity(saved, get(id).value()); } body.hitbox.position = tsf.pos; scripting::on_entity_spawn( - def, id, scripting.components, std::move(args), std::move(componentsMap) - ); + def, id, scripting.components, args, componentsMap); return id; } @@ -188,54 +187,54 @@ void Entities::despawn(entityid_t id) { } } -void Entities::loadEntity(const dynamic::Map_sptr& map) { - entityid_t uid = 0; - std::string defname; - map->num("uid", uid); - map->str("def", defname); - if (uid == 0) { - throw std::runtime_error("could not read entity - invalid UID"); - } +void Entities::loadEntity(const dv::value& map) { + entityid_t uid = map["uid"].asInteger(); + std::string defname = map["def"].asString(); auto& def = level->content->entities.require(defname); 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& body = entity.getRigidbody(); auto& skeleton = entity.getSkeleton(); - if (auto bodymap = map->map(COMP_RIGIDBODY)) { - dynamic::get_vec(bodymap, "vel", body.hitbox.velocity); + if (map.has(COMP_RIGIDBODY)) { + auto& bodymap = map[COMP_RIGIDBODY]; + dv::get_vec(bodymap, "vel", body.hitbox.velocity); std::string bodyTypeName; - bodymap->str("type", bodyTypeName); + map.at("type").get(bodyTypeName); if (auto bodyType = BodyType_from(bodyTypeName)) { body.hitbox.type = *bodyType; } - bodymap->flag("crouch", body.hitbox.crouching); - bodymap->num("damping", body.hitbox.linearDamping); + bodymap["crouch"].asBoolean(body.hitbox.crouching); + bodymap["damping"].asNumber(body.hitbox.linearDamping); } - if (auto tsfmap = map->map(COMP_TRANSFORM)) { - dynamic::get_vec(tsfmap, "pos", transform.pos); - dynamic::get_vec(tsfmap, "size", transform.size); - dynamic::get_mat(tsfmap, "rot", transform.rot); + if (map.has(COMP_TRANSFORM)) { + auto& tsfmap = map[COMP_TRANSFORM]; + dv::get_vec(tsfmap, "pos", transform.pos); + dv::get_vec(tsfmap, "size", transform.size); + dv::get_mat(tsfmap, "rot", transform.rot); } std::string skeletonName = skeleton.config->getName(); - map->str("skeleton", skeletonName); + map.at("skeleton").get(skeletonName); if (skeletonName != skeleton.config->getName()) { skeleton.config = level->content->getSkeleton(skeletonName); } - if (auto skeletonmap = map->map(COMP_SKELETON)) { - if (auto texturesmap = skeletonmap->map("textures")) { - for (auto& [slot, _] : texturesmap->values) { - texturesmap->str(slot, skeleton.textures[slot]); + if (auto found = map.at(COMP_SKELETON)) { + auto& skeletonmap = *found; + if (auto found = skeletonmap.at("textures")) { + 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; - i < std::min(skeleton.pose.matrices.size(), posearr->size()); + i < std::min(skeleton.pose.matrices.size(), posearr.size()); i++) { - dynamic::get_mat(posearr, i, skeleton.pose.matrices[i]); + dv::get_mat(posearr[i], skeleton.pose.matrices[i]); } } } @@ -272,12 +271,12 @@ std::optional Entities::rayCast( } } -void Entities::loadEntities(dynamic::Map_sptr root) { +void Entities::loadEntities(dv::value root) { clean(); - auto list = root->list("data"); - for (size_t i = 0; i < list->size(); i++) { + auto& list = root["data"]; + for (auto& map : list) { try { - loadEntity(list->map(i)); + loadEntity(map); } catch (const std::runtime_error& err) { logger.error() << "could not read entity: " << err.what(); } @@ -288,82 +287,82 @@ void Entities::onSave(const Entity& entity) { scripting::on_entity_save(entity); } -dynamic::Value Entities::serialize(const Entity& entity) { - auto root = dynamic::create_map(); +dv::value Entities::serialize(const Entity& entity) { + auto root = dv::object(); auto& eid = entity.getID(); auto& def = eid.def; - root->put("def", def.name); - root->put("uid", eid.uid); + root["def"] = def.name; + root["uid"] = eid.uid; { auto& transform = entity.getTransform(); - auto& tsfmap = root->putMap(COMP_TRANSFORM); - tsfmap.put("pos", dynamic::to_value(transform.pos)); + auto& tsfmap = root.object(COMP_TRANSFORM); + tsfmap["pos"] = dv::to_value(transform.pos); 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)) { - tsfmap.put("rot", dynamic::to_value(transform.rot)); + tsfmap["rot"] = dv::to_value(transform.rot); } } { auto& rigidbody = entity.getRigidbody(); auto& hitbox = rigidbody.hitbox; - auto& bodymap = root->putMap(COMP_RIGIDBODY); + auto& bodymap = root.object(COMP_RIGIDBODY); if (!rigidbody.enabled) { - bodymap.put("enabled", rigidbody.enabled); + bodymap["enabled"] = false; } 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) { - bodymap.put("damping", rigidbody.hitbox.linearDamping); + bodymap["damping"] = rigidbody.hitbox.linearDamping; if (hitbox.type != def.bodyType) { - bodymap.put("type", to_string(hitbox.type)); + bodymap["type"] = to_string(hitbox.type); } if (hitbox.crouching) { - bodymap.put("crouch", hitbox.crouching); + bodymap["crouch"] = hitbox.crouching; } } } auto& skeleton = entity.getSkeleton(); 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) { - auto& skeletonmap = root->putMap(COMP_SKELETON); + auto& skeletonmap = root.object(COMP_SKELETON); if (def.save.skeleton.textures) { - auto& map = skeletonmap.putMap("textures"); + auto& map = skeletonmap.object("textures"); for (auto& [slot, texture] : skeleton.textures) { - map.put(slot, texture); + map[slot] = texture; } } if (def.save.skeleton.pose) { - auto& list = skeletonmap.putList("pose"); + auto& list = skeletonmap.list("pose"); for (auto& mat : skeleton.pose.matrices) { - list.put(dynamic::to_value(mat)); + list.add(dv::to_value(mat)); } } } auto& scripts = entity.getScripting(); if (!scripts.components.empty()) { - auto& compsMap = root->putMap("comps"); + auto& compsMap = root.object("comps"); for (auto& comp : scripts.components) { auto data = scripting::get_component_value(comp->env, SAVED_DATA_VARNAME); - compsMap.put(comp->name, data); + compsMap[comp->name] = data; } } return root; } -dynamic::List_sptr Entities::serialize(const std::vector& entities) { - auto list = dynamic::create_list(); +dv::value Entities::serialize(const std::vector& entities) { + auto list = dv::list(); for (auto& entity : entities) { if (!entity.getDef().save.enabled) { continue; } level->entities->onSave(entity); - list->put(level->entities->serialize(entity)); + list.add(level->entities->serialize(entity)); } return list; } diff --git a/src/objects/Entities.hpp b/src/objects/Entities.hpp index 9ef2edd6..099fc99b 100644 --- a/src/objects/Entities.hpp +++ b/src/objects/Entities.hpp @@ -5,7 +5,7 @@ #include #include -#include "data/dynamic.hpp" +#include "data/dv.hpp" #include "physics/Hitbox.hpp" #include "typedefs.hpp" #include "util/Clock.hpp" @@ -204,8 +204,8 @@ public: entityid_t spawn( const EntityDef& def, glm::vec3 position, - dynamic::Map_sptr args = nullptr, - dynamic::Map_sptr saved = nullptr, + dv::value args = nullptr, + dv::value saved = nullptr, entityid_t uid = 0 ); @@ -231,17 +231,17 @@ public: entityid_t ignore = -1 ); - void loadEntities(dynamic::Map_sptr map); - void loadEntity(const dynamic::Map_sptr& map); - void loadEntity(const dynamic::Map_sptr& map, Entity entity); + void loadEntities(dv::value map); + void loadEntity(const dv::value& map); + void loadEntity(const dv::value& map, Entity entity); void onSave(const Entity& entity); bool hasBlockingInside(AABB aabb); std::vector getAllInside(AABB aabb); std::vector getAllInRadius(glm::vec3 center, float radius); void despawn(entityid_t id); void despawn(std::vector entities); - dynamic::Value serialize(const Entity& entity); - dynamic::List_sptr serialize(const std::vector& entities); + dv::value serialize(const Entity& entity); + dv::value serialize(const std::vector& entities); void setNextID(entityid_t id) { nextID = id; diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 74fad257..2acbdf46 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -14,6 +14,7 @@ #include "window/Camera.hpp" #include "window/Events.hpp" #include "world/Level.hpp" +#include "data/dv_util.hpp" const float CROUCH_SPEED_MUL = 0.35f; const float RUN_SPEED_MUL = 1.5f; @@ -256,92 +257,68 @@ glm::vec3 Player::getSpawnPoint() const { return spawnpoint; } -std::unique_ptr Player::serialize() const { - auto root = std::make_unique(); - auto& posarr = root->putList("position"); - posarr.put(position.x); - posarr.put(position.y); - posarr.put(position.z); +dv::value Player::serialize() const { + auto root = dv::object(); - auto& rotarr = root->putList("rotation"); - rotarr.put(cam.x); - rotarr.put(cam.y); - rotarr.put(cam.z); + root["position"] = dv::to_value(position); + root["rotation"] = dv::to_value(cam); + root["spawnpoint"] = dv::to_value(spawnpoint); - auto& sparr = root->putList("spawnpoint"); - sparr.put(spawnpoint.x); - sparr.put(spawnpoint.y); - sparr.put(spawnpoint.z); - - root->put("flight", flight); - root->put("noclip", noclip); - root->put("chosen-slot", chosenSlot); - root->put("entity", eid); - root->put("inventory", inventory->serialize()); + root["flight"] = flight; + root["noclip"] = noclip; + root["chosen-slot"] = chosenSlot; + root["entity"] = eid; + root["inventory"] = inventory->serialize(); auto found = std::find(level->cameras.begin(), level->cameras.end(), currentCamera); if (found != level->cameras.end()) { - root->put( - "camera", - level->content->getIndices(ResourceType::CAMERA) - .getName(found - level->cameras.begin()) - ); + root["camera"] = level->content->getIndices(ResourceType::CAMERA) + .getName(found - level->cameras.begin()); } return root; } -void Player::deserialize(dynamic::Map* src) { - auto posarr = src->list("position"); - position.x = posarr->num(0); - position.y = posarr->num(1); - position.z = posarr->num(2); +void Player::deserialize(const dv::value& src) { + const auto& posarr = src["position"]; + + dv::get_vec(posarr, position); camera->position = position; - auto rotarr = src->list("rotation"); - cam.x = rotarr->num(0); - cam.y = rotarr->num(1); - if (rotarr->size() > 2) { - cam.z = rotarr->num(2); + const auto& rotarr = src["rotation"]; + dv::get_vec(rotarr, cam); + + 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")) { - auto sparr = src->list("spawnpoint"); - 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 (src.has("camera")) { + std::string name = src["camera"].asString(); if (auto camera = level->getCamera(name)) { currentCamera = camera; } } } -void Player::convert(dynamic::Map* data, const ContentLUT* lut) { - auto players = data->list("players"); - if (players) { - for (uint i = 0; i < players->size(); i++) { - auto playerData = players->map(i); - if (auto inventory = playerData->map("inventory")) { - Inventory::convert(inventory.get(), lut); +void Player::convert(dv::value& data, const ContentLUT* lut) { + if (data.has("players")) { + auto& players = data["players"]; + for (uint i = 0; i < players.size(); i++) { + auto& playerData = players[i]; + if (playerData.has("inventory")) { + Inventory::convert(playerData["inventory"], lut); } } - } else { - if (auto inventory = data->map("inventory")) { - Inventory::convert(inventory.get(), lut); - } + } else if (data.has("inventory")){ + Inventory::convert(data["inventory"], lut); } } diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index 94ce3096..b144a0ba 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -4,7 +4,6 @@ #include #include -#include "data/dynamic.hpp" #include "interfaces/Object.hpp" #include "interfaces/Serializable.hpp" #include "settings.hpp" @@ -103,10 +102,10 @@ public: void setSpawnPoint(glm::vec3 point); glm::vec3 getSpawnPoint() const; - std::unique_ptr serialize() const override; - void deserialize(dynamic::Map* src) override; + dv::value serialize() const 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 { return objectUID; diff --git a/src/objects/rigging.cpp b/src/objects/rigging.cpp index 3f36daf3..92912f01 100644 --- a/src/objects/rigging.cpp +++ b/src/objects/rigging.cpp @@ -2,7 +2,7 @@ #include "assets/Assets.hpp" #include "coders/json.hpp" -#include "data/dynamic_util.hpp" +#include "data/dv_util.hpp" #include "graphics/core/Model.hpp" #include "graphics/render/ModelBatch.hpp" @@ -139,25 +139,23 @@ Bone* SkeletonConfig::find(std::string_view str) const { } static std::tuple> read_node( - const dynamic::Map_sptr& root, size_t index + const dv::value& root, size_t index ) { std::string name; std::string model; - root->str("name", name); - root->str("model", model); - + root.at("name").get(name); + root.at("model").get(model); glm::vec3 offset(0.0f); - dynamic::get_vec(root, "offset", offset); + dv::get_vec(root, "offset", offset); std::vector> bones; size_t count = 1; - if (auto nodesList = root->list("nodes")) { - for (size_t i = 0; i < nodesList->size(); i++) { - if (const auto& map = nodesList->map(i)) { - auto [subcount, subNode] = read_node(map, index + count); - count += subcount; - bones.push_back(std::move(subNode)); - } + if (auto found = root.at("nodes")) { + const auto& nodesList = *found; + for (const auto& map : nodesList) { + auto [subcount, subNode] = read_node(map, index + count); + count += subcount; + bones.push_back(std::move(subNode)); } } return { @@ -169,10 +167,7 @@ std::unique_ptr SkeletonConfig::parse( std::string_view src, std::string_view file, std::string_view name ) { auto root = json::parse(file, src); - auto rootNodeMap = root->map("root"); - if (rootNodeMap == nullptr) { - throw std::runtime_error("missing 'root' element"); - } + const auto& rootNodeMap = root["root"]; auto [count, rootNode] = read_node(rootNodeMap, 0); return std::make_unique( std::string(name), std::move(rootNode), count diff --git a/src/util/Buffer.hpp b/src/util/Buffer.hpp index 68e185c6..01769f0d 100644 --- a/src/util/Buffer.hpp +++ b/src/util/Buffer.hpp @@ -12,6 +12,7 @@ namespace util { Buffer(size_t length) : ptr(std::make_unique(length)), length(length) { } + Buffer(const Buffer& o) : Buffer(o.data(), o.size()) {} Buffer(std::unique_ptr ptr, size_t length) : ptr(std::move(ptr)), length(length) {} diff --git a/src/voxels/Chunk.hpp b/src/voxels/Chunk.hpp index 14ead964..2c7a9512 100644 --- a/src/voxels/Chunk.hpp +++ b/src/voxels/Chunk.hpp @@ -15,10 +15,6 @@ class Lightmap; class ContentLUT; class Inventory; -namespace dynamic { - class Map; -} - using chunk_inventories_map = std::unordered_map>; diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index c408190b..dc7d5958 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -664,8 +664,8 @@ void Chunks::save(Chunk* chunk) { ) ); auto entities = level->entities->getAllInside(aabb); - auto root = dynamic::create_map(); - root->put("data", level->entities->serialize(entities)); + auto root = dv::object(); + root["data"] = level->entities->serialize(entities); if (!entities.empty()) { level->entities->despawn(std::move(entities)); chunk->flags.entities = true; diff --git a/src/voxels/ChunksStorage.cpp b/src/voxels/ChunksStorage.cpp index 9bc0a4f6..8aeeaf68 100644 --- a/src/voxels/ChunksStorage.cpp +++ b/src/voxels/ChunksStorage.cpp @@ -66,8 +66,9 @@ std::shared_ptr ChunksStorage::create(int x, int z) { auto invs = regions.fetchInventories(chunk->x, chunk->z); chunk->setBlockInventories(std::move(invs)); - if (auto map = regions.fetchEntities(chunk->x, chunk->z)) { - level->entities->loadEntities(std::move(map)); + auto entitiesData = regions.fetchEntities(chunk->x, chunk->z); + if (entitiesData.getType() == dv::value_type::object) { + level->entities->loadEntities(std::move(entitiesData)); chunk->flags.entities = true; } diff --git a/src/window/Events.cpp b/src/window/Events.cpp index a88adcc5..67c305cf 100644 --- a/src/window/Events.cpp +++ b/src/window/Events.cpp @@ -167,10 +167,9 @@ void Events::setPosition(float xpos, float ypos) { #include "coders/json.hpp" #include "coders/toml.hpp" -#include "data/dynamic.hpp" std::string Events::writeBindings() { - dynamic::Map obj; + auto obj = dv::object(); for (auto& entry : Events::bindings) { const auto& binding = entry.second; std::string value; @@ -188,7 +187,7 @@ std::string Events::writeBindings() { default: throw std::runtime_error("unsupported control type"); } - obj.put(entry.first, value); + obj[entry.first] = std::move(value); } return toml::stringify(obj); } @@ -197,26 +196,22 @@ void Events::loadBindings( const std::string& filename, const std::string& source ) { auto map = toml::parse(filename, source); - for (auto& entry : map->values) { - if (auto value = std::get_if(&entry.second)) { - auto [prefix, codename] = util::split_at(*value, ':'); - inputtype type; - int code; - if (prefix == "key") { - type = inputtype::keyboard; - code = static_cast(input_util::keycode_from(codename)); - } else if (prefix == "mouse") { - type = inputtype::mouse; - code = static_cast(input_util::mousecode_from(codename)); - } else { - logger.error() - << "unknown input type: " << prefix << " (binding " - << util::quote(entry.first) << ")"; - continue; - } - Events::bind(entry.first, type, code); + for (auto& [key, value] : map.asObject()) { + auto [prefix, codename] = util::split_at(value.asString(), ':'); + inputtype type; + int code; + if (prefix == "key") { + type = inputtype::keyboard; + code = static_cast(input_util::keycode_from(codename)); + } else if (prefix == "mouse") { + type = inputtype::mouse; + code = static_cast(input_util::mousecode_from(codename)); } else { - logger.error() << "invalid binding entry: " << entry.first; + logger.error() + << "unknown input type: " << prefix << " (binding " + << util::quote(key) << ")"; + continue; } + Events::bind(key, type, code); } } diff --git a/src/world/Level.cpp b/src/world/Level.cpp index 39384b4a..19d3ecb1 100644 --- a/src/world/Level.cpp +++ b/src/world/Level.cpp @@ -1,7 +1,7 @@ #include "Level.hpp" #include "content/Content.hpp" -#include "data/dynamic_util.hpp" +#include "data/dv_util.hpp" #include "items/Inventories.hpp" #include "items/Inventory.hpp" #include "lighting/Lighting.hpp" @@ -33,14 +33,15 @@ Level::Level( auto& cameraIndices = content->getIndices(ResourceType::CAMERA); for (size_t i = 0; i < cameraIndices.size(); i++) { auto camera = std::make_shared(); - if (auto map = cameraIndices.getSavedData(i)) { - dynamic::get_vec(map, "pos", camera->position); - dynamic::get_mat(map, "rot", camera->rotation); - map->flag("perspective", camera->perspective); - map->flag("flipped", camera->flipped); - map->num("zoom", camera->zoom); + auto map = cameraIndices.getSavedData(i); + if (map != nullptr) { + dv::get_vec(map, "pos", camera->position); + dv::get_mat(map, "rot", camera->rotation); + map.at("perspective").get(camera->perspective); + map.at("flipped").get(camera->flipped); + map.at("zoom").get(camera->zoom); float fov = camera->getFov(); - map->num("fov", fov); + map.at("fov").get(fov); camera->setFov(fov); } camera->updateVectors(); @@ -99,13 +100,13 @@ void Level::onSave() { auto& cameraIndices = content->getIndices(ResourceType::CAMERA); for (size_t i = 0; i < cameraIndices.size(); i++) { auto& camera = *cameras.at(i); - auto map = dynamic::create_map(); - map->put("pos", dynamic::to_value(camera.position)); - map->put("rot", dynamic::to_value(camera.rotation)); - map->put("perspective", camera.perspective); - map->put("flipped", camera.flipped); - map->put("zoom", camera.zoom); - map->put("fov", camera.getFov()); + auto map = dv::object(); + map["pos"] = dv::to_value(camera.position); + map["rot"] = dv::to_value(camera.rotation); + map["perspective"] = camera.perspective; + map["flipped"] = camera.flipped; + map["zoom"] = camera.zoom; + map["fov"] = camera.getFov(); cameraIndices.saveData(i, std::move(map)); } } diff --git a/src/world/World.cpp b/src/world/World.cpp index daab3ada..ac182683 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -46,20 +46,21 @@ void World::updateTimers(float delta) { } void World::writeResources(const Content* content) { - auto root = dynamic::Map(); + auto root = dv::object(); for (size_t typeIndex = 0; typeIndex < RESOURCE_TYPES_COUNT; typeIndex++) { auto typeName = to_string(static_cast(typeIndex)); - auto& list = root.putList(typeName); + auto& list = root.list(typeName); auto& indices = content->resourceIndices[typeIndex]; for (size_t i = 0; i < indices.size(); i++) { - auto& map = list.putMap(); - map.put("name", indices.getName(i)); - if (auto data = indices.getSavedData(i)) { - map.put("saved", data); + auto& map = list.object(); + map["name"] = indices.getName(i); + auto data = indices.getSavedData(i); + if (data != nullptr) { + map["saved"] = data; } } } - files::write_json(wfile->getResourcesFile(), &root); + files::write_json(wfile->getResourcesFile(), root); } void World::write(Level* level) { @@ -68,14 +69,14 @@ void World::write(Level* level) { info.nextEntityId = level->entities->peekNextID(); wfile->write(this, content); - auto playerFile = dynamic::Map(); - auto& players = playerFile.putList("players"); + auto playerFile = dv::object(); + auto& players = playerFile.list("players"); for (const auto& object : level->objects) { if (auto player = std::dynamic_pointer_cast(object)) { - players.put(player->serialize()); + players.add(player->serialize()); } } - files::write_json(wfile->getPlayerFile(), &playerFile); + files::write_json(wfile->getPlayerFile(), playerFile); writeResources(content); } @@ -130,11 +131,11 @@ std::unique_ptr World::load( if (!fs::is_regular_file(file)) { logger.warning() << "player.json does not exists"; } else { - auto playerFile = files::read_json(file); - if (playerFile->has("players")) { + auto playerRoot = files::read_json(file); + if (playerRoot.has("players")) { level->objects.clear(); - auto players = playerFile->list("players"); - for (size_t i = 0; i < players->size(); i++) { + const auto& players = playerRoot["players"]; + for (auto& playerMap : players) { auto player = level->spawnObject( level.get(), glm::vec3(0, DEF_PLAYER_Y, 0), @@ -142,12 +143,12 @@ std::unique_ptr World::load( level->inventories->create(DEF_PLAYER_INVENTORY_SIZE), 0 ); - player->deserialize(players->map(i).get()); + player->deserialize(playerMap); level->inventories->store(player->getInventory()); } } else { auto player = level->getObject(0); - player->deserialize(playerFile.get()); + player->deserialize(playerRoot); level->inventories->store(player->getInventory()); } } @@ -200,50 +201,52 @@ const std::vector& World::getPacks() const { return packs; } -void WorldInfo::deserialize(dynamic::Map* root) { - name = root->get("name", name); - generator = root->get("generator", generator); - seed = root->get("seed", seed); +void WorldInfo::deserialize(const dv::value& root) { + name = root["name"].asString(); + generator = root["generator"].asString(generator); + seed = root["seed"].asInteger(seed); if (generator.empty()) { generator = WorldGenerator::DEFAULT; } - if (auto verobj = root->map("version")) { - verobj->num("major", major); - verobj->num("minor", minor); + if (root.has("version")) { + auto& verobj = root["version"]; + major = verobj["major"].asInteger(); + minor = verobj["minor"].asInteger(); } - if (auto timeobj = root->map("time")) { - timeobj->num("day-time", daytime); - timeobj->num("day-time-speed", daytimeSpeed); - timeobj->num("total-time", totalTime); + if (root.has("time")) { + auto& timeobj = root["time"]; + daytime = timeobj["day-time"].asNumber(); + daytimeSpeed = timeobj["day-time-speed"].asNumber(); + totalTime = timeobj["total-time"].asNumber(); } - if (auto weatherobj = root->map("weather")) { - weatherobj->num("fog", fog); + if (root.has("weather")) { + fog = root["weather"]["fog"].asNumber(); } - nextInventoryId = root->get("next-inventory-id", 2); - nextEntityId = root->get("next-entity-id", 1); + nextInventoryId = root["next-inventory-id"].asInteger(2); + nextEntityId = root["next-entity-id"].asInteger(1); } -std::unique_ptr WorldInfo::serialize() const { - auto root = std::make_unique(); +dv::value WorldInfo::serialize() const { + auto root = dv::object(); - auto& versionobj = root->putMap("version"); - versionobj.put("major", ENGINE_VERSION_MAJOR); - versionobj.put("minor", ENGINE_VERSION_MINOR); + auto& versionobj = root.object("version"); + versionobj["major"] = ENGINE_VERSION_MAJOR; + versionobj["minor"] = ENGINE_VERSION_MINOR; - root->put("name", name); - root->put("generator", generator); - root->put("seed", static_cast(seed)); + root["name"] = name; + root["generator"] = generator; + root["seed"] = seed; - auto& timeobj = root->putMap("time"); - timeobj.put("day-time", daytime); - timeobj.put("day-time-speed", daytimeSpeed); - timeobj.put("total-time", totalTime); + auto& timeobj = root.object("time"); + timeobj["day-time"] = daytime; + timeobj["day-time-speed"] = daytimeSpeed; + timeobj["total-time"] = totalTime; - auto& weatherobj = root->putMap("weather"); - weatherobj.put("fog", fog); + auto& weatherobj = root.object("weather"); + weatherobj["fog"] = fog; - root->put("next-inventory-id", nextInventoryId); - root->put("next-entity-id", nextEntityId); + root["next-inventory-id"] = nextInventoryId; + root["next-entity-id"] = nextEntityId; return root; } diff --git a/src/world/World.hpp b/src/world/World.hpp index f5443b2a..4fca2ef3 100644 --- a/src/world/World.hpp +++ b/src/world/World.hpp @@ -6,7 +6,6 @@ #include #include "content/ContentPack.hpp" -#include "data/dynamic.hpp" #include "interfaces/Serializable.hpp" #include "typedefs.hpp" #include "util/timeutil.hpp" @@ -48,8 +47,8 @@ struct WorldInfo : public Serializable { int major = 0, minor = -1; - std::unique_ptr serialize() const override; - void deserialize(dynamic::Map* src) override; + dv::value serialize() const override; + void deserialize(const dv::value& src) override; }; /// @brief holds all world data except the level (chunks and objects) diff --git a/src/world/generator/VoxelStructure.cpp b/src/world/generator/VoxelStructure.cpp index 64b22621..1b7abe4d 100644 --- a/src/world/generator/VoxelStructure.cpp +++ b/src/world/generator/VoxelStructure.cpp @@ -3,8 +3,7 @@ #include #include -#include "data/dynamic.hpp" -#include "data/dynamic_util.hpp" +#include "data/dv_util.hpp" #include "content/Content.hpp" #include "voxels/Block.hpp" #include "voxels/ChunksStorage.hpp" @@ -47,31 +46,31 @@ std::unique_ptr VoxelStructure::create( size, std::move(voxels), std::move(blockNames)); } -std::unique_ptr VoxelStructure::serialize() const { - auto root = std::make_unique(); - root->put("version", STRUCTURE_FORMAT_VERSION); - root->put("size", dynamic::to_value(size)); +dv::value VoxelStructure::serialize() const { + auto root = dv::object(); + root["version"] = STRUCTURE_FORMAT_VERSION; + root["size"] = dv::to_value(size); - auto& blockNamesArr = root->putList("block-names"); + auto& blockNamesArr = root.list("block-names"); for (const auto& name : blockNames) { - blockNamesArr.put(name); + blockNamesArr.add(name); } - auto& voxelsArr = root->putList("voxels"); + auto& voxelsArr = root.list("voxels"); for (size_t i = 0; i < voxels.size(); i++) { - voxelsArr.put(static_cast(voxels[i].id)); - voxelsArr.put(static_cast(blockstate2int(voxels[i].state))); + voxelsArr.add(voxels[i].id); + voxelsArr.add(blockstate2int(voxels[i].state)); } return root; } -void VoxelStructure::deserialize(dynamic::Map* src) { +void VoxelStructure::deserialize(const dv::value& src) { size = glm::ivec3(); - dynamic::get_vec(src, "size", size); + dv::get_vec(src, "size", size); voxels.resize(size.x*size.y*size.z); - auto voxelsArr = src->list("voxels"); + const auto& voxelsArr = src["voxels"]; for (size_t i = 0; i < size.x*size.y*size.z; i++) { - voxels[i].id = voxelsArr->integer(i * 2); - voxels[i].state = int2blockstate(voxelsArr->integer(i * 2 + 1)); + voxels[i].id = voxelsArr[i * 2].asInteger(); + voxels[i].state = int2blockstate(voxelsArr[i * 2 + 1].asInteger()); } } diff --git a/src/world/generator/VoxelStructure.hpp b/src/world/generator/VoxelStructure.hpp index 635175f2..68819653 100644 --- a/src/world/generator/VoxelStructure.hpp +++ b/src/world/generator/VoxelStructure.hpp @@ -30,8 +30,8 @@ struct VoxelStructure : public Serializable { blockNames(std::move(blockNames)) {} - std::unique_ptr serialize() const override; - void deserialize(dynamic::Map* src) override; + dv::value serialize() const override; + void deserialize(const dv::value& src) override; static std::unique_ptr create( Level* level, const glm::ivec3& a, const glm::ivec3& b, bool entities); diff --git a/test/coders/binary_json.cpp b/test/coders/binary_json.cpp index 2a3ecea1..27db4a38 100644 --- a/test/coders/binary_json.cpp +++ b/test/coders/binary_json.cpp @@ -1,6 +1,6 @@ #include -#include "data/dynamic.hpp" +#include "util/Buffer.hpp" #include "coders/binary_json.hpp" TEST(BJSON, EncodeDecode) { @@ -8,28 +8,28 @@ TEST(BJSON, EncodeDecode) { const int bytesSize = 5000; const int year = 2019; 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 bjsonBytes; { - dynamic::Map map; - map.put("name", name); - map.put("year", year); - map.put("score", score); - map.put("data", &srcBytes); + auto object = dv::object(); + object["name"] = name; + object["year"] = year; + object["score"] = score; + object["data"] = srcBytes; - bjsonBytes = json::to_binary(&map, false); + bjsonBytes = json::to_binary(object, false); } { - auto map = json::from_binary(bjsonBytes.data(), bjsonBytes.size()); - EXPECT_EQ(map->get("name"), name); - EXPECT_EQ(map->get("year"), year); - EXPECT_FLOAT_EQ(map->get("score"), score); - auto bytesptr = map->bytes("data"); - const auto& bytes = *bytesptr; + auto object = json::from_binary(bjsonBytes.data(), bjsonBytes.size()); + + EXPECT_EQ(object["name"].asString(), name); + EXPECT_EQ(object["year"].asInteger(), year); + EXPECT_FLOAT_EQ(object["score"].asNumber(), score); + const auto& bytes = object["data"].asBytes(); EXPECT_EQ(bytes.size(), bytesSize); for (int i = 0; i < bytesSize; i++) { EXPECT_EQ(bytes[i], srcBytes[i]); diff --git a/test/coders/json.cpp b/test/coders/json.cpp index 5738559b..be9f0534 100644 --- a/test/coders/json.cpp +++ b/test/coders/json.cpp @@ -8,27 +8,30 @@ TEST(JSON, EncodeDecode) { const int bytesSize = 20; const int year = 2019; const float score = 3.141592; - dynamic::ByteBuffer srcBytes(bytesSize); + const bool visible = true; + 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); + auto object = dv::object(); + object["name"] = name; + object["year"] = year; + object["score"] = score; + object["visible"] = visible; + object["data"] = srcBytes; - text = json::stringify(&map, false, ""); + text = json::stringify(object, false, ""); } { - auto map = json::parse(text); - EXPECT_EQ(map->get("name"), name); - EXPECT_EQ(map->get("year"), year); - EXPECT_FLOAT_EQ(map->get("score"), score); - auto b64string = map->get("data"); + auto object = json::parse(text); + EXPECT_EQ(object["name"].asString(), name); + EXPECT_EQ(object["year"].asInteger(), year); + EXPECT_FLOAT_EQ(object["score"].asNumber(), score); + EXPECT_EQ(object["visible"].asBoolean(), visible); + auto b64string = object["data"].asString(); auto bytes = util::base64_decode(b64string); EXPECT_EQ(bytes.size(), bytesSize); diff --git a/test/data/dv.cpp b/test/data/dv.cpp new file mode 100644 index 00000000..b13e3323 --- /dev/null +++ b/test/data/dv.cpp @@ -0,0 +1,29 @@ +#include + +#include "data/dv.hpp" + +TEST(dv, dv) { + auto value = dv::object(); + { + auto& list = value.list("elements"); + for (int i = 0; i < 10; i++) { + auto& obj = list.object(); + obj["name"] = "user"; + obj["age"] = 90; + obj["confirmed"] = true; + obj["position"] = dv::list({40, -41, 52}); + } + } + { + const auto& list = value["elements"]; + for (const auto& obj : list) { + EXPECT_EQ(obj["name"].asString(), "user"); + EXPECT_EQ(obj["age"].asInteger(), 90); + EXPECT_EQ(obj["confirmed"].asBoolean(), true); + auto& position = obj["position"]; + EXPECT_EQ(position[0].asInteger(), 40); + EXPECT_EQ(position[1].asInteger(), -41); + EXPECT_EQ(position[2].asInteger(), 52); + } + } +}