New world and player files format

This commit is contained in:
MihailRis 2023-12-03 22:03:59 +03:00
parent b62b7bf2bb
commit 2f9244c17c
6 changed files with 168 additions and 79 deletions

View File

@ -320,8 +320,12 @@ void JObject::num(std::string key, uint& dst) const {
JObject* JObject::obj(std::string key) const {
auto found = map.find(key);
if (found != map.end())
return found->second->value.obj;
if (found != map.end()) {
auto& val = found->second;
if (val->type != valtype::object)
return nullptr;
return val->value.obj;
}
return nullptr;
}
@ -500,6 +504,19 @@ JArray* Parser::parseArray() {
Value* Parser::parseValue() {
char next = peek();
valvalue val;
if (next == '-' || next == '+') {
pos++;
number_u num;
valtype type;
if (parseNumber(next == '-' ? -1 : 1, num)) {
val.integer = num.ival;
type = valtype::integer;
} else {
val.decimal = num.fval;
type = valtype::number;
}
return new Value(type, val);
}
if (is_identifier_start(next)) {
string literal = parseName();
if (literal == "true") {
@ -515,7 +532,7 @@ Value* Parser::parseValue() {
val.decimal = NAN;
return new Value(valtype::number, val);
}
throw error("invalid literal");
throw error("invalid literal ");
}
if (next == '{') {
val.obj = parseObject();
@ -525,19 +542,6 @@ Value* Parser::parseValue() {
val.arr = parseArray();
return new Value(valtype::array, val);
}
if (next == '-' || next == '+') {
pos++;
number_u num;
valtype type;
if (parseNumber(next == '-' ? -1 : 1, num)) {
val.integer = num.ival;
type = valtype::integer;
} else {
val.decimal = num.fval;
type = valtype::number;
}
return new Value(type, val);
}
if (is_digit(next)) {
number_u num;
valtype type;

View File

@ -12,6 +12,7 @@
#include <glm/glm.hpp>
// don't ask
using glm::vec3;
using std::cout;
using std::cerr;
@ -24,14 +25,7 @@ ContentLoader::ContentLoader(path folder) : folder(folder) {}
// TODO: add basic validation and logging
Block* ContentLoader::loadBlock(string name, path file) {
string source = files::read_string(file);
unique_ptr<json::JObject> root = nullptr;
try {
root.reset(json::parse(file.string(), source));
} catch (const parsing_error& error) {
cerr << error.errorLog() << endl;
throw std::runtime_error("could not load block def");
}
unique_ptr<json::JObject> root(files::read_json(file));
unique_ptr<Block> def(new Block(name));
// block texturing

View File

@ -14,7 +14,11 @@
#include "../maths/voxmaths.h"
#include "../world/World.h"
#include "../coders/json.h"
#include "../constants.h"
#include <cassert>
#include <string>
#include <iostream>
#include <cstdint>
#include <memory>
@ -33,8 +37,10 @@
using glm::ivec2;
using glm::vec3;
using std::ios;
using std::string;
using std::unique_ptr;
using std::filesystem::path;
namespace fs = std::filesystem;
int bytes2Int(const ubyte* src, size_t offset){
return (src[offset] << 24) | (src[offset+1] << 16) | (src[offset+2] << 8) | (src[offset+3]);
@ -115,15 +121,23 @@ path WorldFiles::getRegionFile(int x, int y) const {
}
path WorldFiles::getPlayerFile() const {
return directory/path("player.bin");
return directory/path("player.json");
}
path WorldFiles::getWorldFile() const {
return directory/path("world.bin");
return directory/path("world.json");
}
path WorldFiles::getBlockIndicesFile() const {
return directory/path("blocks.idx");
path WorldFiles::getIndicesFile() const {
return directory/path("indices.json");
}
path WorldFiles::getOldPlayerFile() const {
return directory/path("player.bin");
}
path WorldFiles::getOldWorldFile() const {
return directory/path("world.bin");
}
ubyte* WorldFiles::getChunk(int x, int y){
@ -220,42 +234,38 @@ void WorldFiles::write(const World* world, const Content* content) {
}
void WorldFiles::writeIndices(const ContentIndices* indices) {
/* Blocks indices */ {
BinaryWriter out;
uint count = indices->countBlockDefs();
out.putInt16(count);
for (uint i = 0; i < count; i++) {
const Block* def = indices->getBlockDef(i);
out.putShortStr(def->name);
}
files::write_bytes(getBlockIndicesFile(),
(const char*)out.data(), out.size());
json::JObject root;
json::JArray& blocks = root.putArray("blocks");
uint count = indices->countBlockDefs();
for (uint i = 0; i < count; i++) {
const Block* def = indices->getBlockDef(i);
blocks.put(def->name);
}
files::write_string(getIndicesFile(), json::stringify(&root, true, " "));
}
void WorldFiles::writeWorldInfo(const World* world) {
BinaryWriter out;
out.putCStr(WORLD_FORMAT_MAGIC);
out.put(WORLD_FORMAT_VERSION);
json::JObject root;
json::JObject& versionobj = root.putObj("version");
versionobj.put("major", ENGINE_VERSION_MAJOR);
versionobj.put("minor", ENGINE_VERSION_MINOR);
root.put("name", world->name);
root.put("seed", world->seed);
out.put(WORLD_SECTION_MAIN);
out.putInt64(world->seed);
out.put(world->name);
json::JObject& timeobj = root.putObj("time");
timeobj.put("day-time", world->daytime);
timeobj.put("day-time-speed", world->daytimeSpeed);
out.put(WORLD_SECTION_DAYNIGHT);
out.putFloat32(world->daytime);
out.putFloat32(world->daytimeSpeed);
files::write_bytes(getWorldFile(), (const char*)out.data(), out.size());
files::write_string(getWorldFile(), json::stringify(&root, true, " "));
}
bool WorldFiles::readWorldInfo(World* world) {
// TODO: remove in v0.16
bool WorldFiles::readOldWorldInfo(World* world) {
size_t length = 0;
ubyte* data = (ubyte*)files::read_bytes(getWorldFile(), length);
if (data == nullptr){
std::cerr << "could not to read world.bin (ignored)" << std::endl;
return false;
}
assert(data != nullptr);
BinaryReader inp(data, length);
inp.checkMagic(WORLD_FORMAT_MAGIC, 8);
/*ubyte version = */inp.get();
@ -274,28 +284,7 @@ bool WorldFiles::readWorldInfo(World* world) {
}
return false;
}
void WorldFiles::writePlayer(Player* player){
vec3 position = player->hitbox->position;
BinaryWriter out;
out.put(SECTION_POSITION);
out.putFloat32(position.x);
out.putFloat32(position.y);
out.putFloat32(position.z);
out.put(SECTION_ROTATION);
out.putFloat32(player->camX);
out.putFloat32(player->camY);
out.put(SECTION_FLAGS);
out.put(player->flight * PLAYER_FLAG_FLIGHT |
player->noclip * PLAYER_FLAG_NOCLIP);
files::write_bytes(getPlayerFile(), (const char*)out.data(), out.size());
}
bool WorldFiles::readPlayer(Player* player) {
bool WorldFiles::readOldPlayer(Player* player) {
size_t length = 0;
ubyte* data = (ubyte*)files::read_bytes(getPlayerFile(), length);
if (data == nullptr){
@ -330,6 +319,85 @@ bool WorldFiles::readPlayer(Player* player) {
player->camera->position = position + vec3(0, 1, 0);
return true;
}
// ----- // ----- //
bool WorldFiles::readWorldInfo(World* world) {
path file = getWorldFile();
if (!fs::is_regular_file(file)) {
// TODO: remove in v0.16
file = getOldWorldFile();
if (fs::is_regular_file(file)) {
readOldWorldInfo(world);
}
std::cerr << "warning: world.json does not exists" << std::endl;
return false;
}
unique_ptr<json::JObject> root(files::read_json(file));
root->num("seed", world->seed);
json::JObject* verobj = root->obj("version");
if (verobj) {
int major=0, minor=-1;
verobj->num("major", major);
verobj->num("minor", minor);
std::cout << "world version: " << major << "." << minor << std::endl;
}
json::JObject* timeobj = root->obj("time");
if (timeobj) {
timeobj->num("day-time", world->daytime);
timeobj->num("day-time-speed", world->daytimeSpeed);
}
return true;
}
void WorldFiles::writePlayer(Player* player){
vec3 position = player->hitbox->position;
json::JObject root;
json::JArray& posarr = root.putArray("position");
posarr.put(position.x);
posarr.put(position.y);
posarr.put(position.z);
json::JArray& rotarr = root.putArray("rotation");
rotarr.put(player->camX);
rotarr.put(player->camY);
root.put("flight", player->flight);
root.put("noclip", player->noclip);
files::write_string(getPlayerFile(), json::stringify(&root, true, " "));
}
bool WorldFiles::readPlayer(Player* player) {
path file = getPlayerFile();
if (!fs::is_regular_file(file)) {
// TODO: remove in v0.16
file = getOldPlayerFile();
if (fs::is_regular_file(file)) {
readOldPlayer(player);
}
std::cerr << "warning: player.json does not exists" << std::endl;
return false;
}
unique_ptr<json::JObject> root(files::read_json(file));
json::JArray* posarr = root->arr("position");
vec3& position = player->hitbox->position;
position.x = posarr->num(0);
position.y = posarr->num(1);
position.z = posarr->num(2);
json::JArray* rotarr = root->arr("rotation");
player->camX = rotarr->num(0);
player->camY = rotarr->num(1);
root->flag("flight", player->flight);
root->flag("noclip", player->noclip);
return true;
}
void WorldFiles::writeRegion(int x, int y, WorldRegion& entry){
ubyte** region = entry.chunksData;
@ -371,4 +439,4 @@ void WorldFiles::writeRegion(int x, int y, WorldRegion& entry){
int2Bytes(offsets[i], (ubyte*)intbuf, 0);
file.write(intbuf, 4);
}
}
}

View File

@ -39,7 +39,14 @@ class WorldFiles {
std::filesystem::path getRegionFile(int x, int y) const;
std::filesystem::path getPlayerFile() const;
std::filesystem::path getWorldFile() const;
std::filesystem::path getBlockIndicesFile() const;
std::filesystem::path getIndicesFile() const;
// TODO: remove in 0.16
std::filesystem::path getOldPlayerFile() const;
std::filesystem::path getOldWorldFile() const;
bool readOldWorldInfo(World* world);
bool readOldPlayer(Player* player);
// --------------------
public:
std::unordered_map<glm::ivec2, WorldRegion> regions;
std::filesystem::path directory;

View File

@ -5,6 +5,7 @@
#include <memory>
#include <stdint.h>
#include <stdexcept>
#include "../coders/json.h"
using std::ios;
using std::string;
@ -71,4 +72,14 @@ bool files::write_string(path filename, const string content) {
}
file << content;
return true;
}
}
json::JObject* files::read_json(path file) {
string text = files::read_string(file);
try {
return json::parse(file.string(), text);
} catch (const parsing_error& error) {
std::cerr << error.errorLog() << std::endl;
throw std::runtime_error("could not to parse "+file.string());
}
}

View File

@ -5,6 +5,10 @@
#include <filesystem>
#include "../typedefs.h"
namespace json {
class JObject;
}
namespace files {
extern bool write_bytes(std::filesystem::path, const char* data, size_t size);
extern uint append_bytes(std::filesystem::path, const char* data, size_t size);
@ -12,6 +16,7 @@ namespace files {
extern char* read_bytes(std::filesystem::path, size_t& length);
extern std::string read_string(std::filesystem::path filename);
extern bool write_string(std::filesystem::path filename, const std::string content);
extern json::JObject* read_json(std::filesystem::path file);
}
#endif /* FILES_FILES_H_ */