From 34d2e6d4007e8a2ec906d7664d4b7ad02dd659d1 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 18 Sep 2024 23:31:18 +0300 Subject: [PATCH] migrate from dynamic::Value to dv::value & total erase namespace 'dynamic' --- src/assets/AssetsLoader.cpp | 41 +-- src/assets/AssetsLoader.hpp | 10 +- src/assets/assetload_funcs.cpp | 15 +- src/coders/binary_json.cpp | 104 +++--- src/coders/binary_json.hpp | 17 +- src/coders/binary_json_dv.cpp | 168 --------- src/coders/commons.cpp | 4 +- src/coders/commons.hpp | 6 +- src/coders/json.cpp | 283 +-------------- src/coders/json.hpp | 20 +- src/coders/obj.cpp | 16 +- src/coders/toml.cpp | 81 ++--- src/coders/toml.hpp | 7 +- src/content/Content.hpp | 16 +- src/content/ContentLUT.cpp | 14 +- src/content/ContentLUT.hpp | 10 +- src/content/ContentLoader.cpp | 355 ++++++++++--------- src/content/ContentLoader.hpp | 12 +- src/content/ContentPack.cpp | 22 +- src/data/dv.cpp | 131 ++++--- src/data/dv.hpp | 310 ++++++++++++---- src/data/dv_util.hpp | 74 ++++ src/data/dynamic.cpp | 345 ------------------ src/data/dynamic.hpp | 190 ---------- src/data/dynamic_fwd.hpp | 35 -- src/data/dynamic_util.hpp | 79 ----- src/files/WorldConverter.cpp | 5 +- src/files/WorldFiles.cpp | 60 ++-- src/files/WorldRegions.cpp | 14 +- src/files/WorldRegions.hpp | 3 +- src/files/files.cpp | 13 +- src/files/files.hpp | 15 +- src/files/settings_io.cpp | 56 +-- src/files/settings_io.hpp | 6 +- src/frontend/hud.cpp | 4 +- src/frontend/locale.cpp | 20 +- src/frontend/menu.cpp | 14 +- src/frontend/menu.hpp | 4 +- src/graphics/ui/elements/TrackBar.hpp | 1 - src/interfaces/Serializable.hpp | 8 +- src/items/Inventory.cpp | 47 +-- src/items/Inventory.hpp | 13 +- src/logic/CommandsInterpreter.cpp | 111 +++--- src/logic/CommandsInterpreter.hpp | 24 +- src/logic/EngineController.cpp | 11 +- src/logic/scripting/lua/libentity.cpp | 7 +- src/logic/scripting/lua/libjson.cpp | 11 +- src/logic/scripting/lua/libtoml.cpp | 8 +- src/logic/scripting/lua/lua_engine.hpp | 1 - src/logic/scripting/lua/lua_util.cpp | 75 ++-- src/logic/scripting/lua/lua_util.hpp | 5 +- src/logic/scripting/scripting.cpp | 20 +- src/logic/scripting/scripting.hpp | 10 +- src/logic/scripting/scripting_functional.cpp | 4 +- src/logic/scripting/scripting_functional.hpp | 7 +- src/objects/Entities.cpp | 122 +++---- src/objects/Entities.hpp | 16 +- src/objects/Player.cpp | 109 +++--- src/objects/Player.hpp | 7 +- src/objects/rigging.cpp | 29 +- src/voxels/Chunk.hpp | 4 - src/voxels/Chunks.cpp | 4 +- src/voxels/ChunksStorage.cpp | 5 +- src/window/Events.cpp | 39 +- src/world/Level.cpp | 31 +- src/world/World.cpp | 99 +++--- src/world/World.hpp | 5 +- test/coders/binary_json.cpp | 42 +-- test/coders/json.cpp | 41 +-- 69 files changed, 1247 insertions(+), 2248 deletions(-) delete mode 100644 src/coders/binary_json_dv.cpp create mode 100644 src/data/dv_util.hpp delete mode 100644 src/data/dynamic.cpp delete mode 100644 src/data/dynamic.hpp delete mode 100644 src/data/dynamic_fwd.hpp delete mode 100644 src/data/dynamic_util.hpp 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..ca18dda9 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++) { + 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..09d16858 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 dv::none; 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 d22e1911..c6dc8df1 100644 --- a/src/coders/binary_json.hpp +++ b/src/coders/binary_json.hpp @@ -4,11 +4,8 @@ #include #include "data/dv.hpp" -#include "data/dynamic_fwd.hpp" -namespace dynamic { - class Map; -} +#include "typedefs.hpp" namespace json { inline constexpr int BJSON_END = 0x0; @@ -26,15 +23,7 @@ namespace json { inline constexpr int BJSON_TYPE_NULL = 0xC; inline constexpr int BJSON_TYPE_CDOCUMENT = 0x1F; - std::vector to_binaryDV(const dv::value& obj, bool compress = false); + std::vector to_binary(const dv::value& obj, bool compress = false); - dv::value from_binaryDV(const ubyte* src, size_t size); - - 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); + dv::value from_binary(const ubyte* src, size_t size); } diff --git a/src/coders/binary_json_dv.cpp b/src/coders/binary_json_dv.cpp deleted file mode 100644 index 821e6849..00000000 --- a/src/coders/binary_json_dv.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include "binary_json.hpp" - -#include - -#include "data/dv.hpp" -#include "byte_utils.hpp" -#include "gzip.hpp" - -using namespace json; - -static void to_binary(ByteBuilder& builder, const dv::value& value) { - switch (value.getType()) { - case dv::value_type::none: - throw std::runtime_error("none value is not implemented"); - case dv::value_type::object: { - const auto bytes = json::to_binaryDV(value); - builder.put(bytes.data(), bytes.size()); - break; - } - case dv::value_type::list: - builder.put(BJSON_TYPE_LIST); - for (const auto& element : value) { - to_binary(builder, element); - } - builder.put(BJSON_END); - break; - case dv::value_type::bytes: { - const auto& bytes = value.asBytes(); - builder.put(BJSON_TYPE_BYTES); - builder.putInt32(bytes.size()); - builder.put(bytes.data(), bytes.size()); - break; - } - case dv::value_type::integer: { - auto val = value.asInteger(); - if (val >= 0 && val <= 255) { - builder.put(BJSON_TYPE_BYTE); - builder.put(val); - } else if (val >= INT16_MIN && val <= INT16_MAX) { - builder.put(BJSON_TYPE_INT16); - builder.putInt16(val); - } else if (val >= INT32_MIN && val <= INT32_MAX) { - builder.put(BJSON_TYPE_INT32); - builder.putInt32(val); - } else { - builder.put(BJSON_TYPE_INT64); - builder.putInt64(val); - } - break; - } - case dv::value_type::number: - builder.put(BJSON_TYPE_NUMBER); - builder.putFloat64(value.asNumber()); - break; - case dv::value_type::boolean: - builder.put(BJSON_TYPE_FALSE + value.asBoolean()); - break; - case dv::value_type::string: - builder.put(BJSON_TYPE_STRING); - builder.put(value.asString()); - break; - } -} - -std::vector json::to_binaryDV(const dv::value& object, bool compress) { - if (compress) { - auto bytes = to_binaryDV(object, false); - return gzip::compress(bytes.data(), bytes.size()); - } - ByteBuilder builder; - // type byte - builder.put(BJSON_TYPE_DOCUMENT); - // document size - builder.putInt32(0); - - // writing entries - for (const auto& [key, value] : object.asObject()) { - builder.putCStr(key.c_str()); - to_binary(builder, value); - } - // terminating byte - builder.put(BJSON_END); - - // updating document size - builder.setInt32(1, builder.size()); - return builder.build(); -} - -static dv::value list_from_binary(ByteReader& reader); -static dv::value object_from_binary(ByteReader& reader); - -static dv::value value_from_binary(ByteReader& reader) { - ubyte typecode = reader.get(); - switch (typecode) { - case BJSON_TYPE_DOCUMENT: - reader.getInt32(); - return object_from_binary(reader); - case BJSON_TYPE_LIST: - return list_from_binary(reader); - case BJSON_TYPE_BYTE: - return reader.get(); - case BJSON_TYPE_INT16: - return reader.getInt16(); - case BJSON_TYPE_INT32: - return reader.getInt32(); - case BJSON_TYPE_INT64: - return reader.getInt64(); - case BJSON_TYPE_NUMBER: - return reader.getFloat64(); - case BJSON_TYPE_FALSE: - case BJSON_TYPE_TRUE: - return (typecode - BJSON_TYPE_FALSE) != 0; - case BJSON_TYPE_STRING: - return reader.getString(); - case BJSON_TYPE_NULL: - return dv::none; - case BJSON_TYPE_BYTES: { - int32_t size = reader.getInt32(); - if (size < 0) { - throw std::runtime_error( - "invalid byte-buffer size "+std::to_string(size)); - } - if (size > reader.remaining()) { - throw std::runtime_error( - "buffer_size > remaining_size "+std::to_string(size)); - } - auto bytes = std::make_shared>( - reader.pointer(), size); - reader.skip(size); - return bytes; - } - } - throw std::runtime_error( - "type support not implemented for <"+std::to_string(typecode)+">"); -} - -static dv::value list_from_binary(ByteReader& reader) { - auto list = dv::list(); - while (reader.peek() != BJSON_END) { - list.add(value_from_binary(reader)); - } - reader.get(); - return list; -} - -static dv::value object_from_binary(ByteReader& reader) { - auto obj = dv::object(); - while (reader.peek() != BJSON_END) { - const char* key = reader.getCString(); - obj[key] = value_from_binary(reader); - } - reader.get(); - return obj; -} - -dv::value json::from_binaryDV(const ubyte* src, size_t size) { - if (size < 2) { - throw std::runtime_error("bytes length is less than 2"); - } - if (src[0] == gzip::MAGIC[0] && src[1] == gzip::MAGIC[1]) { - // reading compressed document - auto data = gzip::decompress(src, size); - return from_binaryDV(data.data(), data.size()); - } else { - ByteReader reader(src, size); - return value_from_binary(reader); - } -} 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 a57f5b1f..049eeb40 100644 --- a/src/coders/json.cpp +++ b/src/coders/json.cpp @@ -6,29 +6,17 @@ #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(); -public: - Parser(std::string_view filename, std::string_view source); - - std::unique_ptr parse(); -}; - -class ParserDV : BasicParser { dv::value parseList(); dv::value parseObject(); dv::value parseValue(); public: - ParserDV(std::string_view filename, std::string_view source); + Parser(std::string_view filename, std::string_view source); dv::value parse(); }; @@ -46,22 +34,6 @@ inline void newline( } } -void stringifyObj( - const Map* obj, - std::stringstream& ss, - int indent, - const std::string& indentstr, - bool nice -); - -void stringifyArr( - const List* list, - std::stringstream& ss, - int indent, - const std::string& indentstr, - bool nice -); - void stringifyObj( const dv::value& obj, std::stringstream& ss, @@ -78,34 +50,6 @@ void stringifyList( bool nice ); -void stringifyValue( - const 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"; - } -} - void stringifyValue( const dv::value& value, std::stringstream& ss, @@ -146,74 +90,6 @@ void stringifyValue( } } -void stringifyArr( - const List* list, - std::stringstream& ss, - int indent, - const std::string& indentstr, - bool nice -) { - if (list == nullptr) { - ss << "nullptr"; - return; - } - if (list->values.empty()) { - ss << "[]"; - return; - } - ss << "["; - for (size_t i = 0; i < list->size(); i++) { - if (i > 0 || nice) { - newline(ss, nice, indent, indentstr); - } - const Value& value = list->values[i]; - stringifyValue(value, ss, indent + 1, indentstr, nice); - if (i + 1 < list->size()) { - ss << ','; - } - } - if (nice) { - newline(ss, true, indent - 1, indentstr); - } - ss << ']'; -} - -void stringifyObj( - const Map* obj, - std::stringstream& ss, - int indent, - const std::string& indentstr, - bool nice -) { - if (obj == nullptr) { - ss << "nullptr"; - return; - } - if (obj->values.empty()) { - ss << "{}"; - return; - } - ss << "{"; - size_t index = 0; - for (auto& entry : obj->values) { - const std::string& key = entry.first; - if (index > 0 || nice) { - newline(ss, nice, indent, indentstr); - } - const Value& value = entry.second; - ss << util::escape(key) << ": "; - stringifyValue(value, ss, indent + 1, indentstr, nice); - index++; - if (index < obj->values.size()) { - ss << ','; - } - } - if (nice) { - newline(ss, true, indent - 1, indentstr); - } - ss << '}'; -} - void stringifyList( const dv::value& list, std::stringstream& ss, @@ -273,30 +149,6 @@ 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 -) { - std::stringstream ss; - stringifyValue(value, ss, 1, indent, nice); - return ss.str(); -} - -std::string json::stringifyDV( const dv::value& value, bool nice, const std::string& indent ) { std::stringstream ss; @@ -308,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"); @@ -316,118 +168,7 @@ std::unique_ptr Parser::parse() { return parseObject(); } -std::unique_ptr Parser::parseObject() { - expect('{'); - auto obj = std::make_unique(); - auto& map = obj->values; - while (peek() != '}') { - if (peek() == '#') { - skipLine(); - continue; - } - std::string key = parseName(); - char next = peek(); - if (next != ':') { - throw error("':' expected"); - } - pos++; - map.insert(std::make_pair(key, parseValue())); - next = peek(); - if (next == ',') { - pos++; - } else if (next == '}') { - break; - } else { - throw error("',' expected"); - } - } - pos++; - return obj; -} - -std::unique_ptr Parser::parseList() { - expect('['); - auto arr = std::make_unique(); - auto& values = arr->values; - while (peek() != ']') { - if (peek() == '#') { - skipLine(); - continue; - } - values.push_back(parseValue()); - - char next = peek(); - if (next == ',') { - pos++; - } else if (next == ']') { - break; - } else { - throw error("',' expected"); - } - } - pos++; - return arr; -} - -Value Parser::parseValue() { - char next = peek(); - if (next == '-' || next == '+' || is_digit(next)) { - auto numeric = parseNumber(); - if (std::holds_alternative(numeric)) { - return std::get(numeric); - } - return std::get(numeric); - } - if (is_identifier_start(next)) { - std::string literal = parseName(); - if (literal == "true") { - return true; - } else if (literal == "false") { - return false; - } else if (literal == "inf") { - return INFINITY; - } else if (literal == "nan") { - return NAN; - } - throw error("invalid literal "); - } - if (next == '{') { - return Map_sptr(parseObject().release()); - } - if (next == '[') { - return List_sptr(parseList().release()); - } - if (next == '"' || next == '\'') { - pos++; - return parseString(next); - } - throw error("unexpected character '" + std::string({next}) + "'"); -} - -dynamic::Map_sptr json::parse( - std::string_view filename, std::string_view source -) { - Parser parser(filename, source); - return parser.parse(); -} - -dynamic::Map_sptr json::parse(std::string_view source) { - return parse("", source); -} - -ParserDV::ParserDV(std::string_view filename, std::string_view source) - : BasicParser(filename, source) { -} - -dv::value ParserDV::parse() { - char next = peek(); - if (next != '{') { - throw error("'{' expected"); - } - return parseObject(); -} - -dv::value ParserDV::parseObject() { +dv::value Parser::parseObject() { expect('{'); auto object = dv::object(); while (peek() != '}') { @@ -455,7 +196,7 @@ dv::value ParserDV::parseObject() { return object; } -dv::value ParserDV::parseList() { +dv::value Parser::parseList() { expect('['); auto list = dv::list(); while (peek() != ']') { @@ -478,14 +219,14 @@ dv::value ParserDV::parseList() { return list; } -dv::value ParserDV::parseValue() { +dv::value Parser::parseValue() { char next = peek(); if (next == '-' || next == '+' || is_digit(next)) { auto numeric = parseNumber(); - if (std::holds_alternative(numeric)) { - return std::get(numeric); + if (numeric.isInteger()) { + return numeric.asInteger(); } - return std::get(numeric); + return numeric.asNumber(); } if (is_identifier_start(next)) { std::string literal = parseName(); @@ -513,13 +254,13 @@ dv::value ParserDV::parseValue() { throw error("unexpected character '" + std::string({next}) + "'"); } -dv::value json::parseDV( +dv::value json::parse( std::string_view filename, std::string_view source ) { - ParserDV parser(filename, source); + Parser parser(filename, source); return parser.parse(); } -dv::value json::parseDV(std::string_view source) { - return parseDV("", 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 a9ce5b1e..f79b5d46 100644 --- a/src/coders/json.hpp +++ b/src/coders/json.hpp @@ -2,31 +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 parseDV(std::string_view filename, std::string_view source); - dv::value parseDV(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 - ); - - std::string stringifyDV( 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..9fc5d4d4 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; } - readSection("", *root); + readSection("", root); return 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 1931c262..b656a129 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 @@ -122,18 +122,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 { @@ -148,12 +148,12 @@ public: return MISSING; } - dynamic::Map_sptr getSavedData(size_t index) 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 8e670152..28148e1c 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 f0b92c07..77531ba5 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 45abb7f9..5c10b6e3 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( @@ -458,9 +476,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() { @@ -486,7 +504,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; }; @@ -500,9 +518,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 @@ -544,9 +563,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 @@ -588,9 +608,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 @@ -669,11 +690,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; } @@ -681,10 +700,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 5087378b..da5d6fbc 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; @@ -18,11 +19,6 @@ class ContentBuilder; class ContentPackRuntime; struct ContentPackStats; -namespace dynamic { - class Map; - class List; -} - class ContentLoader { const ContentPack* pack; ContentPackRuntime* runtime; @@ -40,7 +36,7 @@ class ContentLoader { EntityDef& def, const std::string& full, const std::string& name ); - static void loadCustomBlockModel(Block& def, dynamic::Map* primitives); + static void loadCustomBlockModel(Block& def, const dv::value& primitives); static void loadBlockMaterial(BlockMaterial& def, const fs::path& file); void loadBlock( Block& def, const std::string& name, const fs::path& file @@ -51,13 +47,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 index 4330cfc7..323698f6 100644 --- a/src/data/dv.cpp +++ b/src/data/dv.cpp @@ -23,16 +23,12 @@ namespace dv { } value& value::operator[](const key_t& key) { - if (type == value_type::object) { - return (*val.object)[key]; - } - throw std::runtime_error("value is not an object"); + check_type(type, value_type::object); + return (*val.object)[key]; } const value& value::operator[](const key_t& key) const { - if (type == value_type::object) { - return (*val.object)[key]; - } - throw std::runtime_error("value is not an object"); + check_type(type, value_type::object); + return (*val.object)[key]; } value& value::operator=(const objects::Bytes& bytes) { @@ -40,23 +36,17 @@ namespace dv { } value& value::operator[](size_t index) { - if (type == value_type::list) { - return (*val.list)[index]; - } - throw std::runtime_error("value is not a list"); + check_type(type, value_type::list); + return (*val.list)[index]; } const value& value::operator[](size_t index) const { - if (type == value_type::list) { - return (*val.list)[index]; - } - throw std::runtime_error("value is not a list"); + check_type(type, value_type::list); + return (*val.list)[index]; } void value::add(value v) { - if (type == value_type::list) { - return val.list->push(std::move(v)); - } - throw std::runtime_error("value is not a list"); + check_type(type, value_type::list); + return val.list->push_back(std::move(v)); } value& value::object(const key_t& key) { @@ -72,54 +62,42 @@ namespace dv { } value& value::object() { - if (type == value_type::list) { - return val.list->add(std::make_shared()); - } - throw std::runtime_error("value is not a list"); + check_type(type, value_type::list); + val.list->push_back(std::make_shared()); + return val.list->operator[](val.list->size()-1); } value& value::list() { - if (type == value_type::list) { - return val.list->add(std::make_shared()); - } - throw std::runtime_error("value is not a 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() { - if (type == value_type::list) { - return val.list->begin(); - } - throw std::runtime_error("value is not a list"); + check_type(type, value_type::list); + return val.list->begin(); } list_t::iterator value::end() { - if (type == value_type::list) { - return val.list->end(); - } - throw std::runtime_error("value is not a list"); + check_type(type, value_type::list); + return val.list->end(); } list_t::const_iterator value::begin() const { - if (type == value_type::list) { - const auto& constlist = *val.list; - return constlist.begin(); - } - throw std::runtime_error("value is not a list"); + check_type(type, value_type::list); + const auto& constlist = *val.list; + return constlist.begin(); } list_t::const_iterator value::end() const { - if (type == value_type::list) { - const auto& constlist = *val.list; - return constlist.end(); - } - throw std::runtime_error("value is not a list"); + check_type(type, value_type::list); + const auto& constlist = *val.list; + return constlist.end(); } const std::string& value::asString() const { - if (type == value_type::string) { - return *val.string; - } - throw std::runtime_error("type error"); + check_type(type, value_type::string); + return *val.string; } integer_t value::asInteger() const { @@ -128,7 +106,8 @@ namespace dv { } else if (type == value_type::number) { return static_cast(val.number); } - throw std::runtime_error("type error"); + throw_type_error(type, value_type::integer); + return 0; // unreachable } number_t value::asNumber() const { @@ -137,7 +116,8 @@ namespace dv { } else if (type == value_type::integer) { return static_cast(val.integer); } - throw std::runtime_error("type error"); + throw_type_error(type, value_type::integer); + return 0; // unreachable } boolean_t value::asBoolean() const { @@ -146,31 +126,26 @@ namespace dv { } else if (type == value_type::integer) { return val.integer != 0; } - throw std::runtime_error("type error"); + throw_type_error(type, value_type::boolean); + return false; // unreachable } objects::Bytes& value::asBytes() { - if (type == value_type::bytes) { - return *val.bytes; - } - throw std::runtime_error("type error"); + check_type(type, value_type::bytes); + return *val.bytes; } const objects::Bytes& value::asBytes() const { - if (type == value_type::bytes) { - return *val.bytes; - } - throw std::runtime_error("type error"); + check_type(type, value_type::bytes); + return *val.bytes; } const objects::Object& value::asObject() const { - if (type == value_type::object) { - return *val.object; - } - throw std::runtime_error("type error"); + check_type(type, value_type::object); + return *val.object; } - const size_t value::size() const { + size_t value::size() const { switch (type) { case value_type::list: return val.list->size(); @@ -179,8 +154,30 @@ namespace dv { case value_type::string: return val.string->size(); default: - throw std::runtime_error("type error"); + return 0; } } + + bool value::has(const key_t& k) const { + if (type == value_type::object) { + return val.object->find(k) != val.object->end(); + } + return false; + } + + void value::erase(const key_t& key) { + check_type(type, value_type::object); + val.object->erase(key); + } + + void value::erase(size_t index) { + check_type(type, value_type::list); + val.list->erase(val.list->begin() + index); + } } +#include "coders/json.hpp" + +std::ostream& operator<<(std::ostream& stream, const dv::value& value) { + return stream << json::stringify(value, false); +} diff --git a/src/data/dv.hpp b/src/data/dv.hpp index ab20c22d..d6f95aa9 100644 --- a/src/data/dv.hpp +++ b/src/data/dv.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace util { @@ -30,10 +31,18 @@ namespace dv { string }; - namespace objects { - class Object; - class List; - using Bytes = util::Buffer; + 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; @@ -45,6 +54,58 @@ namespace dv { 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 elementreference { + value* ptr; + + elementreference(value* ptr) : ptr(ptr) {} + + inline operator bool() const { + return ptr != nullptr; + } + + inline value& operator*() { + return *ptr; + } + + inline const value& operator*() const { + return *ptr; + } + + bool get(std::string& dst) const; + bool get(bool& dst) const; + bool get(int8_t& dst) const; + bool get(int16_t& dst) const; + bool get(int32_t& dst) const; + bool get(int64_t& dst) const; + bool get(uint8_t& dst) const; + bool get(uint16_t& dst) const; + bool get(uint32_t& dst) const; + bool get(uint64_t& dst) const; + bool get(float& dst) const; + bool get(double& dst) const; + }; + + inline void throw_type_error(value_type got, value_type expected) { + // place breakpoint here to find cause + throw std::runtime_error( + "type error: expected " + type_name(expected) + ", got " + + type_name(got) + ); + } + + inline void check_type(value_type got, value_type expected) { + if (got != expected) { + throw_type_error(got, expected); + } + } + class value { value_type type = value_type::none; union value_u { @@ -149,6 +210,10 @@ namespace dv { } } + inline value& operator=(std::nullptr_t) { + return setNone(); + } + inline value& operator=(int8_t v) { return setInteger(v); } @@ -302,6 +367,10 @@ namespace dv { 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; @@ -310,6 +379,14 @@ namespace dv { 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); @@ -342,93 +419,109 @@ namespace dv { return type; } - const size_t size() const; + std::string asString(std::string def) const { + if (type != value_type::string) { + return def; + } + return *val.string; + } - const size_t length() const { + std::string asString(const char* s) const { + return asString(std::string(s)); + } + + integer_t asBoolean(boolean_t def) const { + switch (type) { + case value_type::boolean: + return val.boolean; + default: + return def; + } + } + + integer_t asInteger(integer_t def) const { + switch (type) { + case value_type::integer: + return val.integer; + case value_type::number: + return static_cast(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; + } + } + + elementreference at(const key_t& k) const { + check_type(type, value_type::object); + const auto& found = val.object->find(k); + if (found == val.object->end()) { + return elementreference(nullptr); + } + return elementreference(&found->second); + } + + elementreference at(size_t index) { + check_type(type, value_type::list); + return elementreference(&val.list->at(index)); + } + + const elementreference at(size_t index) const { + check_type(type, value_type::list); + return elementreference(&val.list->at(index)); + } + + bool has(const key_t& k) const; + + size_t size() const; + + size_t length() const { return size(); } inline bool empty() const { return size() == 0; } + + inline bool isString() const { + return type == value_type::string; + } + inline bool isObject() const { + return type == value_type::object; + } + inline bool isList() const { + return type == value_type::list; + } + inline bool isInteger() const { + return type == value_type::integer; + } + inline bool isNumber() const { + return type == value_type::number; + } }; inline value none = value(); -} -namespace dv::objects { - class Object { - map_t map; - public: - Object() = default; - Object(std::initializer_list pairs) : map(pairs) {} - Object(const Object&) = delete; - ~Object() = default; + inline bool is_numeric(const value& val) { + return val.isInteger() && val.isNumber(); + } - reference operator[](const key_t& key) { - return map[key]; - } - const_reference operator[](const key_t& key) const { - return map.at(key); - } - - map_t::const_iterator begin() const { - return map.begin(); - } - map_t::const_iterator end() const { - return map.end(); - } - - const size_t size() const { - return map.size(); - } - }; - - class List { - list_t list; - public: - List() = default; - List(std::initializer_list values) : list(values) {} - List(const List&) = delete; - ~List() = default; - - reference operator[](std::size_t index) { - return list.at(index); - } - - const_reference operator[](std::size_t index) const { - return list.at(index); - } - - void push(value v) { - list.push_back(std::move(v)); - } - - reference add(value v) { - list.push_back(std::move(v)); - return list[list.size()-1]; - } - - auto begin() { - return list.begin(); - } - auto end() { - return list.end(); - } - - list_t::const_iterator begin() const { - return list.begin(); - } - list_t::const_iterator end() const { - return list.end(); - } - - const size_t size() const { - return list.size(); - } - }; + using to_string_func = std::function; } namespace dv { + inline const std::string& type_name(const value& value) { + return type_name(value.getType()); + } + inline value object() { return std::make_shared(); } @@ -440,4 +533,67 @@ namespace dv { 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 elementreference::get(std::string& dst) const { + if (ptr) { + dst = ptr->asString(); + return true; + } + return false; + } + + inline bool elementreference::get(bool& dst) const { + if (ptr) { + dst = ptr->asBoolean(); + return true; + } + return false; + } + + inline bool elementreference::get(int8_t& dst) const { + return get_to_int(ptr, dst); + } + inline bool elementreference::get(int16_t& dst) const { + return get_to_int(ptr, dst); + } + inline bool elementreference::get(int32_t& dst) const { + return get_to_int(ptr, dst); + } + inline bool elementreference::get(int64_t& dst) const { + return get_to_int(ptr, dst); + } + inline bool elementreference::get(uint8_t& dst) const { + return get_to_int(ptr, dst); + } + inline bool elementreference::get(uint16_t& dst) const { + return get_to_int(ptr, dst); + } + inline bool elementreference::get(uint32_t& dst) const { + return get_to_int(ptr, dst); + } + inline bool elementreference::get(uint64_t& dst) const { + return get_to_int(ptr, dst); + } + inline bool elementreference::get(float& dst) const { + return get_to_num(ptr, dst); + } + inline bool elementreference::get(double& dst) const { + return get_to_num(ptr, dst); + } } + +std::ostream& operator<<(std::ostream& stream, const dv::value& value); diff --git a/src/data/dv_util.hpp b/src/data/dv_util.hpp new file mode 100644 index 00000000..4a6bf033 --- /dev/null +++ b/src/data/dv_util.hpp @@ -0,0 +1,74 @@ +#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++) { + vec[i] = list[i].asNumber(); + } + } + + 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 81ba5be0..00000000 --- a/src/data/dynamic_util.hpp +++ /dev/null @@ -1,79 +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::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); - } - } - } - - 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_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 d47d64c9..c6941f1c 100644 --- a/src/files/WorldRegions.cpp +++ b/src/files/WorldRegions.cpp @@ -6,10 +6,10 @@ #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" @@ -364,7 +364,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()); } @@ -467,21 +467,21 @@ 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; + return dv::none; } auto map = json::from_binary(data, bytesSize); - if (map->size() == 0) { - return nullptr; + if (map.size() == 0) { + return dv::none; } 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 89962079..24457d44 100644 --- a/src/interfaces/Serializable.hpp +++ b/src/interfaces/Serializable.hpp @@ -1,12 +1,12 @@ #pragma once -#include "coders/json.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..29145eae 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(); @@ -173,18 +173,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 +193,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 +210,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 +232,7 @@ public: break; } case ArgType::number: - if (!dynamic::is_numeric(value)) { + if (!dv::is_numeric(value)) { if (arg->optional) { return false; } else { @@ -242,9 +243,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 +253,35 @@ public: return true; } - dynamic::Value fetchOrigin( + dv::value fetchOrigin( CommandsInterpreter* interpreter, Argument* arg ) { - if (dynamic::is_numeric(arg->origin)) { + if (dv::is_numeric(arg->origin)) { return arg->origin; - } else if (auto string = std::get_if(&arg->origin)) { - return (*interpreter)[*string]; + } else if (arg->origin.getType() == dv::value_type::string) { + return (*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 +293,13 @@ public: return origin; } auto value = parseValue(); - if (origin.index() == 0) { + if (origin == nullptr) { return value; } return applyRelative(arg, value, origin); } - inline dynamic::Value performKeywordArg( + inline dv::value performKeywordArg( CommandsInterpreter* interpreter, Command* command, const std::string& key @@ -322,14 +322,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 +338,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,21 +356,22 @@ 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)); @@ -380,20 +380,21 @@ public: value = applyRelative(arg, value, fetchOrigin(interpreter, arg)); } - args->put(value); + args.add(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}; diff --git a/src/logic/CommandsInterpreter.hpp b/src/logic/CommandsInterpreter.hpp index 11144720..62ad5a1f 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 7e0d59c3..1fcdb672 100644 --- a/src/logic/EngineController.cpp +++ b/src/logic/EngineController.cpp @@ -88,14 +88,13 @@ 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}); } diff --git a/src/logic/scripting/lua/libentity.cpp b/src/logic/scripting/lua/libentity.cpp index e4c49c8f..c5acfafa 100644 --- a/src/logic/scripting/lua/libentity.cpp +++ b/src/logic/scripting/lua/libentity.cpp @@ -50,12 +50,9 @@ 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); return 1; 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 23ab4c80..219f9df6 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 @@ -394,8 +395,8 @@ namespace lua { return glm::vec4(r / 255, g / 255, b / 255, a / 255); } - int pushvalue(lua::State*, const dynamic::Value& value); - dynamic::Value tovalue(lua::State*, int idx); + int pushvalue(lua::State*, const dv::value& value); + 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 9fa17a91..6ff27c65 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -325,7 +325,7 @@ bool scripting::on_item_break_block( ); } -dynamic::Value scripting::get_component_value( +dv::value scripting::get_component_value( const scriptenv& env, const std::string& name ) { auto L = lua::get_main_thread(); @@ -333,15 +333,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 + dv::value args, + dv::value saved ) { auto L = lua::get_main_thread(); lua::requireglobal(L, STDCOMP); @@ -364,8 +364,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); } @@ -377,8 +377,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); } @@ -559,10 +559,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 94723f05..fffe6d60 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" @@ -87,15 +87,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 + dv::value args, + dv::value saved ); void on_entity_despawn(const Entity& entity); void on_entity_grounded(const Entity& entity, float force); @@ -111,7 +111,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..0b3a60c4 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( +dv::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..7192adf7 100644 --- a/src/logic/scripting/scripting_functional.hpp +++ b/src/logic/scripting/scripting_functional.hpp @@ -3,13 +3,12 @@ #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&)>; runnable create_runnable( const scriptenv& env, @@ -71,7 +70,7 @@ namespace scripting { const std::string& file = "" ); - dynamic::to_string_func create_tostring( + dv::to_string_func create_tostring( const scriptenv& env, const std::string& src, const std::string& file = "" diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index b50b4318..5cbefe81 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,9 +166,9 @@ 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; @@ -188,54 +188,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 +272,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 +288,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..e7a3302b 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -256,92 +256,71 @@ 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::list({position.x, position.y, position.z}); + root["rotation"] = dv::list({cam.x, cam.y, cam.z}); + root["spawnpoint"] = dv::list({spawnpoint.x, spawnpoint.y, spawnpoint.z}); - 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"]; + position.x = posarr[0].asNumber(); + position.y = posarr[1].asNumber(); + position.z = posarr[2].asNumber(); 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"]; + cam.x = rotarr[0].asNumber(); + cam.y = rotarr[1].asNumber(); + cam.z = rotarr[2].asNumber(); + + 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..bbf3349b 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"); - } + 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/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 d22ec3cc..0e194dce 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -746,8 +746,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 6d9b1f03..2c2eef24 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 f8358960..7f7606e4 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -45,20 +45,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) { @@ -67,14 +68,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); } @@ -129,11 +130,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), @@ -141,12 +142,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()); } } @@ -199,50 +200,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 = WorldGenerators::getDefaultGeneratorID(); } - 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/test/coders/binary_json.cpp b/test/coders/binary_json.cpp index aae6f669..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,41 +8,7 @@ TEST(BJSON, EncodeDecode) { const int bytesSize = 5000; const int year = 2019; const float score = 3.141592; - dynamic::ByteBuffer 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); - - bjsonBytes = json::to_binary(&map, 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; - EXPECT_EQ(bytes.size(), bytesSize); - for (int i = 0; i < bytesSize; i++) { - EXPECT_EQ(bytes[i], srcBytes[i]); - } - } -} - -TEST(BJSON, EncodeDecodeDV) { - const std::string name = "JSON-encoder"; - const int bytesSize = 5000; - const int year = 2019; - const float score = 3.141592; - dynamic::ByteBuffer srcBytes(bytesSize); + dv::objects::Bytes srcBytes(bytesSize); for (int i = 0; i < bytesSize; i ++) { srcBytes[i] = rand(); } @@ -55,10 +21,10 @@ TEST(BJSON, EncodeDecodeDV) { object["score"] = score; object["data"] = srcBytes; - bjsonBytes = json::to_binaryDV(object, false); + bjsonBytes = json::to_binary(object, false); } { - auto object = json::from_binaryDV(bjsonBytes.data(), bjsonBytes.size()); + auto object = json::from_binary(bjsonBytes.data(), bjsonBytes.size()); EXPECT_EQ(object["name"].asString(), name); EXPECT_EQ(object["year"].asInteger(), year); diff --git a/test/coders/json.cpp b/test/coders/json.cpp index 7d2f0dbe..f1c28cc6 100644 --- a/test/coders/json.cpp +++ b/test/coders/json.cpp @@ -8,42 +8,7 @@ TEST(JSON, EncodeDecode) { const int bytesSize = 20; const int year = 2019; const float score = 3.141592; - dynamic::ByteBuffer srcBytes(bytesSize); - for (int i = 0; i < bytesSize; i ++) { - srcBytes[i] = rand(); - } - - std::string text; - { - dynamic::Map map; - map.put("name", name); - map.put("year", year); - map.put("score", score); - map.put("data", &srcBytes); - - text = json::stringify(&map, false, ""); - } - { - auto map = json::parse(text); - EXPECT_EQ(map->get("name"), name); - EXPECT_EQ(map->get("year"), year); - EXPECT_FLOAT_EQ(map->get("score"), score); - auto b64string = map->get("data"); - - auto bytes = util::base64_decode(b64string); - EXPECT_EQ(bytes.size(), bytesSize); - for (int i = 0; i < bytesSize; i++) { - EXPECT_EQ(bytes[i], srcBytes[i]); - } - } -} - -TEST(JSON, EncodeDecodeDV) { - const std::string name = "JSON-encoder"; - const int bytesSize = 20; - const int year = 2019; - const float score = 3.141592; - dynamic::ByteBuffer srcBytes(bytesSize); + dv::objects::Bytes srcBytes(bytesSize); for (int i = 0; i < bytesSize; i ++) { srcBytes[i] = rand(); } @@ -56,10 +21,10 @@ TEST(JSON, EncodeDecodeDV) { object["score"] = score; object["data"] = srcBytes; - text = json::stringifyDV(object, false, ""); + text = json::stringify(object, false, ""); } { - auto object = json::parseDV(text); + auto object = json::parse(text); EXPECT_EQ(object["name"].asString(), name); EXPECT_EQ(object["year"].asInteger(), year); EXPECT_FLOAT_EQ(object["score"].asNumber(), score);