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

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

View File

@ -8,7 +8,6 @@
#include "constants.hpp"
#include "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<SoundCfg>(map->get("keep-pcm", false)));
std::make_shared<SoundCfg>(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<dynamic::Type>(value.index())) {
case dynamic::Type::string:
processPreload(tag, std::get<std::string>(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<dynamic::Map_sptr>(value);
auto name = map->get<std::string>("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
}

View File

@ -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:

View File

@ -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<std::pair<std::string, int>>& 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);
}

View File

@ -2,38 +2,38 @@
#include <stdexcept>
#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<Type>(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<Map_sptr>(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<List_sptr>(value)->values) {
for (const auto& element : value) {
to_binary(builder, element);
}
builder.put(BJSON_END);
break;
case Type::bytes: {
const auto& bytes = std::get<ByteBuffer_sptr>(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<integer_t>(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<number_t>(value));
builder.putFloat64(value.asNumber());
break;
case Type::boolean:
builder.put(BJSON_TYPE_FALSE + std::get<bool>(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<std::string>(value));
builder.put(value.asString());
break;
}
}
static std::unique_ptr<List> array_from_binary(ByteReader& reader);
static std::unique_ptr<Map> object_from_binary(ByteReader& reader);
std::vector<ubyte> json::to_binary(const Map* obj, bool compress) {
std::vector<ubyte> 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<ubyte> 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<ubyte> json::to_binary(const Map* obj, bool compress) {
return builder.build();
}
std::vector<ubyte> json::to_binary(const Value& value, bool compress) {
if (auto map = std::get_if<Map_sptr>(&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<integer_t>(reader.get());
return reader.get();
case BJSON_TYPE_INT16:
return static_cast<integer_t>(reader.getInt16());
return reader.getInt16();
case BJSON_TYPE_INT32:
return static_cast<integer_t>(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<ByteBuffer>(reader.pointer(), size);
auto bytes = std::make_shared<util::Buffer<ubyte>>(
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<List> array_from_binary(ByteReader& reader) {
auto array = std::make_unique<List>();
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<Map> object_from_binary(ByteReader& reader) {
auto obj = std::make_unique<Map>();
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<Map> 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<Map> 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<Map_sptr>(&value)) {
return *map;
} else {
throw std::runtime_error("root value is not an object");
}
return value_from_binary(reader);
}
}

View File

@ -4,11 +4,8 @@
#include <vector>
#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<ubyte> to_binaryDV(const dv::value& obj, bool compress = false);
std::vector<ubyte> to_binary(const dv::value& obj, bool compress = false);
dv::value from_binaryDV(const ubyte* src, size_t size);
std::vector<ubyte> to_binary(
const dynamic::Map* obj, bool compress = false
);
std::vector<ubyte> to_binary(
const dynamic::Value& obj, bool compress = false
);
std::shared_ptr<dynamic::Map> from_binary(const ubyte* src, size_t size);
dv::value from_binary(const ubyte* src, size_t size);
}

View File

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

View File

@ -258,7 +258,7 @@ int64_t BasicParser::parseSimpleInt(int base) {
return value;
}
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() &&

View File

@ -3,7 +3,7 @@
#include <stdexcept>
#include <string>
#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);

View File

@ -6,29 +6,17 @@
#include <memory>
#include <sstream>
#include "data/dynamic.hpp"
#include "util/stringutil.hpp"
#include "commons.hpp"
using namespace json;
using namespace dynamic;
class Parser : BasicParser {
std::unique_ptr<dynamic::List> parseList();
std::unique_ptr<dynamic::Map> parseObject();
dynamic::Value parseValue();
public:
Parser(std::string_view filename, std::string_view source);
std::unique_ptr<dynamic::Map> parse();
};
class ParserDV : BasicParser {
dv::value parseList();
dv::value 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<Map_sptr>(&value)) {
stringifyObj(map->get(), ss, indent, indentstr, nice);
} else if (auto listptr = std::get_if<List_sptr>(&value)) {
stringifyArr(listptr->get(), ss, indent, indentstr, nice);
} else if (auto bytesptr = std::get_if<ByteBuffer_sptr>(&value)) {
auto bytes = bytesptr->get();
ss << "\"" << util::base64_encode(bytes->data(), bytes->size());
ss << "\"";
} else if (auto flag = std::get_if<bool>(&value)) {
ss << (*flag ? "true" : "false");
} else if (auto num = std::get_if<number_t>(&value)) {
ss << std::setprecision(15) << *num;
} else if (auto num = std::get_if<integer_t>(&value)) {
ss << *num;
} else if (auto str = std::get_if<std::string>(&value)) {
ss << util::escape(*str);
} else {
ss << "null";
}
}
void stringifyValue(
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<Map> Parser::parse() {
dv::value Parser::parse() {
char next = peek();
if (next != '{') {
throw error("'{' expected");
@ -316,118 +168,7 @@ std::unique_ptr<Map> Parser::parse() {
return parseObject();
}
std::unique_ptr<Map> Parser::parseObject() {
expect('{');
auto obj = std::make_unique<Map>();
auto& map = obj->values;
while (peek() != '}') {
if (peek() == '#') {
skipLine();
continue;
}
std::string key = parseName();
char next = peek();
if (next != ':') {
throw error("':' expected");
}
pos++;
map.insert(std::make_pair(key, parseValue()));
next = peek();
if (next == ',') {
pos++;
} else if (next == '}') {
break;
} else {
throw error("',' expected");
}
}
pos++;
return obj;
}
std::unique_ptr<List> Parser::parseList() {
expect('[');
auto arr = std::make_unique<List>();
auto& values = arr->values;
while (peek() != ']') {
if (peek() == '#') {
skipLine();
continue;
}
values.push_back(parseValue());
char next = peek();
if (next == ',') {
pos++;
} else if (next == ']') {
break;
} else {
throw error("',' expected");
}
}
pos++;
return arr;
}
Value Parser::parseValue() {
char next = peek();
if (next == '-' || next == '+' || is_digit(next)) {
auto numeric = parseNumber();
if (std::holds_alternative<integer_t>(numeric)) {
return std::get<integer_t>(numeric);
}
return std::get<number_t>(numeric);
}
if (is_identifier_start(next)) {
std::string literal = parseName();
if (literal == "true") {
return true;
} else if (literal == "false") {
return false;
} else if (literal == "inf") {
return INFINITY;
} else if (literal == "nan") {
return NAN;
}
throw error("invalid literal ");
}
if (next == '{') {
return Map_sptr(parseObject().release());
}
if (next == '[') {
return List_sptr(parseList().release());
}
if (next == '"' || next == '\'') {
pos++;
return parseString(next);
}
throw error("unexpected character '" + std::string({next}) + "'");
}
dynamic::Map_sptr json::parse(
std::string_view filename, std::string_view source
) {
Parser parser(filename, source);
return parser.parse();
}
dynamic::Map_sptr json::parse(std::string_view source) {
return parse("<string>", source);
}
ParserDV::ParserDV(std::string_view filename, std::string_view source)
: BasicParser(filename, source) {
}
dv::value ParserDV::parse() {
char next = peek();
if (next != '{') {
throw error("'{' expected");
}
return parseObject();
}
dv::value ParserDV::parseObject() {
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<integer_t>(numeric)) {
return std::get<integer_t>(numeric);
if (numeric.isInteger()) {
return numeric.asInteger();
}
return std::get<number_t>(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("<string>", source);
dv::value json::parse(std::string_view source) {
return parse("<string>", source);
}

View File

@ -2,31 +2,15 @@
#include <string>
#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=" "
);
}

View File

@ -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();

View File

@ -6,7 +6,6 @@
#include <iomanip>
#include <sstream>
#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<dynamic::Map_sptr>(&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<dynamic::Map_sptr>(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<dynamic::Map_sptr>(&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();

View File

@ -2,14 +2,15 @@
#include <string>
#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

View File

@ -8,8 +8,8 @@
#include <unordered_map>
#include <vector>
#include "data/dynamic_fwd.hpp"
#include "content_fwd.hpp"
#include "data/dv.hpp"
using DrawGroups = std::set<ubyte>;
template <class K, class V>
@ -122,18 +122,18 @@ public:
class ResourceIndices {
std::vector<std::string> names;
std::unordered_map<std::string, size_t> indices;
std::unique_ptr<std::vector<dynamic::Map_sptr>> savedData;
std::unique_ptr<std::vector<dv::value>> savedData;
public:
ResourceIndices()
: savedData(std::make_unique<std::vector<dynamic::Map_sptr>>()) {
: savedData(std::make_unique<std::vector<dv::value>>()) {
}
static constexpr size_t MISSING = SIZE_MAX;
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 {

View File

@ -20,9 +20,11 @@ ContentLUT::ContentLUT(
template <class T>
static constexpr size_t get_entries_count(
const ContentUnitIndices<T>& indices, const dynamic::List_sptr& list
const ContentUnitIndices<T>& indices, const dv::value& list
) {
return list ? std::max(list->size(), indices.count()) : indices.count();
return list != nullptr
? std::max(list.size(), indices.count())
: indices.count();
}
std::shared_ptr<ContentLUT> ContentLUT::create(
@ -36,8 +38,8 @@ std::shared_ptr<ContentLUT> 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> ContentLUT::create(
auto lut = std::make_shared<ContentLUT>(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;

View File

@ -6,7 +6,7 @@
#include <vector>
#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<U>& 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<U>& 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 {

View File

@ -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<std::string> detected;
@ -68,25 +68,23 @@ bool ContentLoader::fixPackIndices(
std::vector<std::string> 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<size_t>(type)].add(
pack->id + ":" + list->str(i), nullptr
pack->id + ":" + list[i].asString(), nullptr
);
}
}

View File

@ -5,6 +5,7 @@
#include <string>
#include "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();

View File

@ -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()}
);
}
}

View File

@ -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<objects::Object>());
}
throw std::runtime_error("value is not a list");
check_type(type, value_type::list);
val.list->push_back(std::make_shared<objects::Object>());
return val.list->operator[](val.list->size()-1);
}
value& value::list() {
if (type == value_type::list) {
return val.list->add(std::make_shared<objects::List>());
}
throw std::runtime_error("value is not a list");
check_type(type, value_type::list);
val.list->push_back(std::make_shared<objects::List>());
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<integer_t>(val.number);
}
throw std::runtime_error("type error");
throw_type_error(type, value_type::integer);
return 0; // unreachable
}
number_t value::asNumber() const {
@ -137,7 +116,8 @@ namespace dv {
} else if (type == value_type::integer) {
return static_cast<number_t>(val.integer);
}
throw std::runtime_error("type error");
throw_type_error(type, value_type::integer);
return 0; // unreachable
}
boolean_t value::asBoolean() const {
@ -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);
}

View File

@ -6,6 +6,7 @@
#include <vector>
#include <cstring>
#include <stdexcept>
#include <functional>
#include <unordered_map>
namespace util {
@ -30,10 +31,18 @@ namespace dv {
string
};
namespace objects {
class Object;
class List;
using Bytes = util::Buffer<byte_t>;
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<int>(type)];
}
class value;
@ -45,6 +54,58 @@ namespace dv {
using reference = value&;
using const_reference = const value&;
namespace objects {
using Object = std::unordered_map<key_t, value>;
using List = std::vector<value>;
using Bytes = util::Buffer<byte_t>;
}
/// @brief nullable value reference returned by value.at(...)
struct elementreference {
value* ptr;
elementreference(value* ptr) : ptr(ptr) {}
inline operator bool() const {
return ptr != nullptr;
}
inline value& operator*() {
return *ptr;
}
inline const value& operator*() const {
return *ptr;
}
bool get(std::string& dst) const;
bool get(bool& dst) const;
bool get(int8_t& dst) const;
bool get(int16_t& dst) const;
bool get(int32_t& dst) const;
bool get(int64_t& dst) const;
bool get(uint8_t& dst) const;
bool get(uint16_t& dst) const;
bool get(uint32_t& dst) const;
bool get(uint64_t& dst) const;
bool get(float& dst) const;
bool get(double& dst) const;
};
inline void throw_type_error(value_type got, value_type expected) {
// place breakpoint here to find cause
throw std::runtime_error(
"type error: expected " + type_name(expected) + ", got " +
type_name(got)
);
}
inline void check_type(value_type got, value_type expected) {
if (got != expected) {
throw_type_error(got, expected);
}
}
class value {
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<integer_t>(val.number);
default:
return def;
}
}
integer_t asNumber(integer_t def) const {
switch (type) {
case value_type::integer:
return static_cast<number_t>(val.integer);
case value_type::number:
return val.number;
default:
return def;
}
}
elementreference at(const key_t& k) const {
check_type(type, value_type::object);
const auto& found = val.object->find(k);
if (found == val.object->end()) {
return elementreference(nullptr);
}
return elementreference(&found->second);
}
elementreference at(size_t index) {
check_type(type, value_type::list);
return elementreference(&val.list->at(index));
}
const elementreference at(size_t index) const {
check_type(type, value_type::list);
return elementreference(&val.list->at(index));
}
bool has(const key_t& k) const;
size_t size() const;
size_t length() const {
return size();
}
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<pair> 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<value> values) : list(values) {}
List(const List&) = delete;
~List() = default;
reference operator[](std::size_t index) {
return list.at(index);
}
const_reference operator[](std::size_t index) const {
return list.at(index);
}
void push(value v) {
list.push_back(std::move(v));
}
reference add(value v) {
list.push_back(std::move(v));
return list[list.size()-1];
}
auto begin() {
return list.begin();
}
auto end() {
return list.end();
}
list_t::const_iterator begin() const {
return list.begin();
}
list_t::const_iterator end() const {
return list.end();
}
const size_t size() const {
return list.size();
}
};
using to_string_func = std::function<std::string(const value&)>;
}
namespace dv {
inline const std::string& type_name(const value& value) {
return type_name(value.getType());
}
inline value object() {
return std::make_shared<objects::Object>();
}
@ -440,4 +533,67 @@ namespace dv {
inline value list(std::initializer_list<value> values) {
return std::make_shared<objects::List>(values);
}
template<typename T> inline bool get_to_int(value* ptr, T& dst) {
if (ptr) {
dst = ptr->asInteger();
return true;
}
return false;
}
template<typename T> inline bool get_to_num(value* ptr, T& dst) {
if (ptr) {
dst = ptr->asNumber();
return true;
}
return false;
}
inline bool elementreference::get(std::string& dst) const {
if (ptr) {
dst = ptr->asString();
return true;
}
return false;
}
inline bool elementreference::get(bool& dst) const {
if (ptr) {
dst = ptr->asBoolean();
return true;
}
return false;
}
inline bool elementreference::get(int8_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(int16_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(int32_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(int64_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(uint8_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(uint16_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(uint32_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(uint64_t& dst) const {
return get_to_int(ptr, dst);
}
inline bool elementreference::get(float& dst) const {
return get_to_num(ptr, dst);
}
inline bool elementreference::get(double& dst) const {
return get_to_num(ptr, dst);
}
}
std::ostream& operator<<(std::ostream& stream, const dv::value& value);

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

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,6 @@
#include <utility>
#include "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 {

View File

@ -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<ContentPack>& packs) {
template <class T>
static void write_indices(
const ContentUnitIndices<T>& indices, dynamic::List& list
const ContentUnitIndices<T>& 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<WorldInfo> WorldFiles::readWorldInfo() {
@ -128,23 +127,22 @@ std::optional<WorldInfo> 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<std::string>& 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 {

View File

@ -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<ubyte[]> 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<Inventory>(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;
}

View File

@ -8,7 +8,6 @@
#include <mutex>
#include <unordered_map>
#include "data/dynamic_fwd.hpp"
#include "typedefs.hpp"
#include "util/BufferPool.hpp"
#include "voxels/Chunk.hpp"
@ -198,7 +197,7 @@ public:
std::unique_ptr<ubyte[]> getChunk(int x, int z);
std::unique_ptr<light_t[]> 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);

View File

@ -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<dynamic::Map> files::read_json(const fs::path& filename) {
dv::value files::read_json(const fs::path& filename) {
std::string text = files::read_string(filename);
return json::parse(filename.string(), text);
}
std::shared_ptr<dynamic::Map> files::read_binary_json(const fs::path& file) {
dv::value files::read_binary_json(const fs::path& file) {
size_t size;
std::unique_ptr<ubyte[]> bytes(files::read_bytes(file, size));
auto bytes = files::read_bytes(file, size);
return json::from_binary(bytes.get(), size);
}
std::shared_ptr<dynamic::Map> files::read_toml(const fs::path& file) {
dv::value files::read_toml(const fs::path& file) {
return toml::parse(file.u8string(), files::read_string(file));
}

View File

@ -7,13 +7,10 @@
#include <vector>
#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<dynamic::Map> read_json(const fs::path& file);
std::shared_ptr<dynamic::Map> read_binary_json(const fs::path& file);
std::shared_ptr<dynamic::Map> 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<std::string> read_list(const fs::path& file);
}

View File

@ -80,12 +80,13 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) {
builder.add("do-write-lights", &settings.debug.doWriteLights);
}
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<NumberSetting*>(setting)) {
return static_cast<number_t>(number->get());
} else if (auto integer = dynamic_cast<IntegerSetting*>(setting)) {
@ -121,20 +122,26 @@ bool SettingsHandler::has(const std::string& name) const {
}
template <class T>
static void set_numeric_value(T* setting, const dynamic::Value& value) {
if (auto num = std::get_if<integer_t>(&value)) {
setting->set(*num);
} else if (auto num = std::get_if<number_t>(&value)) {
setting->set(*num);
} else if (auto flag = std::get_if<bool>(&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<FlagSetting*>(setting)) {
set_numeric_value(flag, value);
} else if (auto string = dynamic_cast<StringSetting*>(setting)) {
if (auto num = std::get_if<integer_t>(&value)) {
string->set(std::to_string(*num));
} else if (auto num = std::get_if<number_t>(&value)) {
string->set(std::to_string(*num));
} else if (auto flag = std::get_if<bool>(&value)) {
string->set(*flag ? "true" : "false");
} else if (auto str = std::get_if<std::string>(&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(

View File

@ -5,7 +5,7 @@
#include <unordered_map>
#include <vector>
#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;

View File

@ -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<InventoryView>(element.getNode());
auto inventory = invview ? invview->getInventory() : nullptr;
std::vector<Value> args;
std::vector<dv::value> args;
args.emplace_back(inventory ? inventory.get()->getId() : 0);
for (int i = 0; i < 3; i++) {
args.emplace_back(static_cast<integer_t>(blockPos[i]));

View File

@ -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<dynamic::Map_sptr>(&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";
}

View File

@ -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<Value> args;
std::vector<dv::value> 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<dynamic::Value> args) {
UiDocument* menus::show(Engine* engine, const std::string& name, std::vector<dv::value> 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<dyn
}
void menus::show_process_panel(Engine* engine, const std::shared_ptr<Task>& task, const std::wstring& text) {
using namespace dynamic;
uint initialWork = task->getWorkTotal();
auto menu = engine->getGUI()->getMenu();

View File

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

View File

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

View File

@ -1,12 +1,12 @@
#pragma once
#include "coders/json.hpp"
#include "data/dv.hpp"
#include <memory>
class Serializable {
public:
virtual ~Serializable() { }
virtual std::unique_ptr<dynamic::Map> 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;
};

View File

@ -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<dynamic::Map> Inventory::serialize() const {
auto map = std::make_unique<dynamic::Map>();
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");
}
}
}

View File

@ -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<dynamic::Map> 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;

View File

@ -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 <typename T>
inline bool typeCheck(
Argument* arg, const dynamic::Value& value, const std::string& tname
Argument* arg, dv::value_type type, const dv::value& value, const std::string& tname
) {
if (!std::holds_alternative<T>(value)) {
if (value.getType() != type) {
if (arg->optional) {
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<std::string>(&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<std::string>(&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<integer_t>(arg, value, "integer");
return typeCheck(arg, dv::value_type::integer, value, "integer");
case ArgType::string:
if (!std::holds_alternative<std::string>(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<std::string>(&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<integer_t>(0);
@ -338,18 +338,17 @@ public:
if (hasNext() && peekNoJump() != ' ') {
value = parseValue();
if (auto string = std::get_if<std::string>(&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<std::string>(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<std::string>(&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<std::string>(&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};

View File

@ -5,7 +5,7 @@
#include <unordered_map>
#include <vector>
#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<dynamic::Value(
CommandsInterpreter*, dynamic::List_sptr args, dynamic::Map_sptr kwargs
using executor_func = std::function<dv::value(
CommandsInterpreter*, dv::value args, dv::value kwargs
)>;
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<CommandsRepository> repository;
std::unordered_map<std::string, dynamic::Value> variables;
std::unordered_map<std::string, dv::value> variables;
public:
CommandsInterpreter()
: repository(std::make_unique<CommandsRepository>()) {
@ -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];
}

View File

@ -88,14 +88,13 @@ void show_convert_request(
static void show_content_missing(
Engine* engine, const std::shared_ptr<ContentLUT>& 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});
}

View File

@ -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<dynamic::Map_sptr>(&value)) {
args = *map;
}
args = lua::tovalue(L, 3);
}
level->entities->spawn(def, pos, args);
return 1;

View File

@ -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<dynamic::Map_sptr>(&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) {

View File

@ -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<dynamic::Map_sptr>(&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>", string);
auto value = std::make_unique<dynamic::Value>(element);
return lua::pushvalue(L, *value);
return lua::pushvalue(L, element);
}
const luaL_Reg tomllib[] = {

View File

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

View File

@ -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<bool>(&value)) {
pushboolean(L, *flag);
} else if (auto* num = std::get_if<integer_t>(&value)) {
pushinteger(L, *num);
} else if (auto* num = std::get_if<number_t>(&value)) {
pushnumber(L, *num);
} else if (auto* str = std::get_if<std::string>(&value)) {
pushstring(L, *str);
} else if (auto listptr = std::get_if<List_sptr>(&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<Map_sptr>(&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<dynamic::Value>& args) {
return [=](const std::vector<dv::value>& 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;
};
}

View File

@ -4,6 +4,7 @@
#include <typeinfo>
#include <unordered_map>
#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());

View File

@ -325,7 +325,7 @@ bool scripting::on_item_break_block(
);
}
dynamic::Value scripting::get_component_value(
dv::value scripting::get_component_value(
const scriptenv& env, const std::string& name
) {
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<std::unique_ptr<UserComponent>>& 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<dynamic::Value> args
UiDocument* layout, std::vector<dv::value> args
) {
auto argsptr =
std::make_shared<std::vector<dynamic::Value>>(std::move(args));
std::make_shared<std::vector<dv::value>>(std::move(args));
std::string name = layout->getId() + ".open";
lua::emit_event(lua::get_main_thread(), name, [=](auto L) {
for (const auto& value : *argsptr) {

View File

@ -6,7 +6,7 @@
#include <string>
#include <vector>
#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<std::unique_ptr<UserComponent>>& 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<dynamic::Value> args);
void on_ui_open(UiDocument* layout, std::vector<dv::value> args);
void on_ui_progress(UiDocument* layout, int workDone, int totalWork);

View File

@ -160,7 +160,7 @@ vec2supplier scripting::create_vec2_supplier(
};
}
dynamic::to_string_func scripting::create_tostring(
dv::to_string_func scripting::create_tostring(
const scriptenv& env, const std::string& src, const std::string& file
) {
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, " ");
};

View File

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

View File

@ -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::RaycastResult> 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<Entity>& entities) {
auto list = dynamic::create_list();
dv::value Entities::serialize(const std::vector<Entity>& 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;
}

View File

@ -5,7 +5,7 @@
#include <optional>
#include <vector>
#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<Entity> getAllInside(AABB aabb);
std::vector<Entity> getAllInRadius(glm::vec3 center, float radius);
void despawn(entityid_t id);
void despawn(std::vector<Entity> entities);
dynamic::Value serialize(const Entity& entity);
dynamic::List_sptr serialize(const std::vector<Entity>& entities);
dv::value serialize(const Entity& entity);
dv::value serialize(const std::vector<Entity>& entities);
void setNextID(entityid_t id) {
nextID = id;

View File

@ -256,92 +256,71 @@ glm::vec3 Player::getSpawnPoint() const {
return spawnpoint;
}
std::unique_ptr<dynamic::Map> Player::serialize() const {
auto root = std::make_unique<dynamic::Map>();
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);
}
}

View File

@ -4,7 +4,6 @@
#include <memory>
#include <optional>
#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<dynamic::Map> 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;

View File

@ -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<size_t, std::unique_ptr<Bone>> read_node(
const dynamic::Map_sptr& root, size_t index
const dv::value& root, size_t index
) {
std::string name;
std::string 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<std::unique_ptr<Bone>> 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> 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<SkeletonConfig>(
std::string(name), std::move(rootNode), count

View File

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

View File

@ -746,8 +746,8 @@ void Chunks::save(Chunk* chunk) {
)
);
auto entities = level->entities->getAllInside(aabb);
auto 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;

View File

@ -66,8 +66,9 @@ std::shared_ptr<Chunk> 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;
}

View File

@ -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<std::string>(&entry.second)) {
auto [prefix, codename] = util::split_at(*value, ':');
inputtype type;
int code;
if (prefix == "key") {
type = inputtype::keyboard;
code = static_cast<int>(input_util::keycode_from(codename));
} else if (prefix == "mouse") {
type = inputtype::mouse;
code = static_cast<int>(input_util::mousecode_from(codename));
} else {
logger.error()
<< "unknown input type: " << prefix << " (binding "
<< util::quote(entry.first) << ")";
continue;
}
Events::bind(entry.first, type, code);
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<int>(input_util::keycode_from(codename));
} else if (prefix == "mouse") {
type = inputtype::mouse;
code = static_cast<int>(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);
}
}

View File

@ -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<Camera>();
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));
}
}

View File

@ -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<ResourceType>(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<Player>(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<Level> 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<Player>(
level.get(),
glm::vec3(0, DEF_PLAYER_Y, 0),
@ -141,12 +142,12 @@ std::unique_ptr<Level> 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<Player>(0);
player->deserialize(playerFile.get());
player->deserialize(playerRoot);
level->inventories->store(player->getInventory());
}
}
@ -199,50 +200,52 @@ const std::vector<ContentPack>& 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<dynamic::Map> WorldInfo::serialize() const {
auto root = std::make_unique<dynamic::Map>();
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<integer_t>(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;
}

View File

@ -6,7 +6,6 @@
#include <vector>
#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<dynamic::Map> 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)

View File

@ -1,6 +1,6 @@
#include <gtest/gtest.h>
#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<ubyte> bjsonBytes;
{
dynamic::Map map;
map.put("name", name);
map.put("year", year);
map.put("score", score);
map.put("data", &srcBytes);
bjsonBytes = json::to_binary(&map, false);
}
{
auto map = json::from_binary(bjsonBytes.data(), bjsonBytes.size());
EXPECT_EQ(map->get<std::string>("name"), name);
EXPECT_EQ(map->get<integer_t>("year"), year);
EXPECT_FLOAT_EQ(map->get<number_t>("score"), score);
auto bytesptr = map->bytes("data");
const auto& bytes = *bytesptr;
EXPECT_EQ(bytes.size(), bytesSize);
for (int i = 0; i < bytesSize; i++) {
EXPECT_EQ(bytes[i], srcBytes[i]);
}
}
}
TEST(BJSON, EncodeDecodeDV) {
const std::string name = "JSON-encoder";
const int bytesSize = 5000;
const int year = 2019;
const float score = 3.141592;
dynamic::ByteBuffer srcBytes(bytesSize);
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);

View File

@ -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<std::string>("name"), name);
EXPECT_EQ(map->get<integer_t>("year"), year);
EXPECT_FLOAT_EQ(map->get<number_t>("score"), score);
auto b64string = map->get<std::string>("data");
auto bytes = util::base64_decode(b64string);
EXPECT_EQ(bytes.size(), bytesSize);
for (int i = 0; i < bytesSize; i++) {
EXPECT_EQ(bytes[i], srcBytes[i]);
}
}
}
TEST(JSON, EncodeDecodeDV) {
const std::string name = "JSON-encoder";
const int bytesSize = 20;
const int year = 2019;
const float score = 3.141592;
dynamic::ByteBuffer srcBytes(bytesSize);
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);