World indices check

This commit is contained in:
MihailRis 2023-12-07 15:16:37 +03:00
parent 551b230b94
commit 636cb0c44c
12 changed files with 197 additions and 40 deletions

View File

@ -64,7 +64,15 @@ Content::~Content() {
delete indices;
}
Block* Content::require(std::string id) const {
Block* Content::findBlock(string id) const {
auto found = blockDefs.find(id);
if (found == blockDefs.end()) {
return nullptr;
}
return found->second;
}
Block* Content::requireBlock(string id) const {
auto found = blockDefs.find(id);
if (found == blockDefs.end()) {
throw std::runtime_error("missing block "+id);

View File

@ -55,7 +55,8 @@ public:
std::unordered_map<std::string, Block*> blockDefs);
~Content();
Block* require(std::string id) const;
Block* findBlock(std::string id) const;
Block* requireBlock(std::string id) const;
};
#endif // CONTENT_CONTENT_H_

View File

@ -0,0 +1,69 @@
#include "ContentIndexLUT.h"
#include <iostream>
#include <memory>
#include "Content.h"
#include "../constants.h"
#include "../files/files.h"
#include "../coders/json.h"
#include "../voxels/Block.h"
using std::string;
using std::unique_ptr;
using std::filesystem::path;
ContentIndexLUT::ContentIndexLUT(size_t blocksCount, const Content* content) {
blocks = new blockid_t[blocksCount];
blockNames = new string[blocksCount];
for (size_t i = 0; i < blocksCount; i++) {
blocks[i] = i;
}
ContentIndices* indices = content->indices;
for (size_t i = 0; i < indices->countBlockDefs(); i++) {
blockNames[i] = indices->getBlockDef(i)->name;
}
}
ContentIndexLUT::~ContentIndexLUT() {
delete[] blockNames;
delete[] blocks;
}
ContentIndexLUT* ContentIndexLUT::create(const path& filename, const Content* content) {
auto& indices = content->indices;
unique_ptr<json::JObject> root(files::read_json(filename));
json::JArray* blocksarr = root->arr("blocks");
size_t blocks_c = blocksarr
? std::max(blocksarr->size(), indices->countBlockDefs())
: indices->countBlockDefs();
unique_ptr<ContentIndexLUT> lut(new ContentIndexLUT(blocks_c, content));
bool conflicts = false;
// TODO: implement world files convert feature using ContentIndexLUT report
for (size_t i = 0; i < blocksarr->size(); i++) {
string name = blocksarr->str(i);
Block* def = content->findBlock(name);
if (def) {
if (i != def->rt.id) {
std::cerr << "block id has changed from ";
std::cerr << def->rt.id << " to " << i << std::endl;
conflicts = true;
}
lut->setBlock(i, name, def->rt.id);
} else {
std::cerr << "unknown block: " << name << std::endl;
lut->setBlock(i, name, i);
conflicts = true;
}
}
if (conflicts) {
return lut.release();
} else {
return nullptr;
}
}

View File

@ -0,0 +1,33 @@
#ifndef CONTENT_CONTENT_INDEX_LUT_H_
#define CONTENT_CONTENT_INDEX_LUT_H_
#include "../typedefs.h"
#include <string>
#include <filesystem>
class Content;
/* Content indices lookup table or report
used to convert world with different indices
Building with indices.json */
class ContentIndexLUT {
blockid_t* blocks;
std::string* blockNames;
public:
ContentIndexLUT(size_t blocks, const Content* content);
~ContentIndexLUT();
inline blockid_t getBlockId(blockid_t index) {
return blocks[index];
}
inline void setBlock(blockid_t index, std::string name, blockid_t id) {
blocks[index] = id;
blockNames[index] = name;
}
static ContentIndexLUT* create(const std::filesystem::path& filename,
const Content* content);
};
#endif // CONTENT_CONTENT_INDEX_LUT_H_

View File

@ -447,6 +447,7 @@ bool WorldFiles::readWorldInfo(World* world) {
}
unique_ptr<json::JObject> root(files::read_json(file));
root->str("name", world->name);
root->num("seed", world->seed);
json::JObject* verobj = root->obj("version");

View File

@ -56,9 +56,8 @@ Panel* create_main_menu_panel(Engine* engine, PagesControl* menu) {
EngineSettings& settings = engine->getSettings();
auto folder = paths->getWorldsFolder()/u8path(name);
World* world = new World(name, folder, 42, settings);
auto screen = new LevelScreen(engine,
world->load(settings, engine->getContent()));
Level* level = World::load(folder, settings, engine->getContent());
auto screen = new LevelScreen(engine, level);
engine->setScreen(shared_ptr<Screen>(screen));
});
worldsPanel->add(button);
@ -146,8 +145,8 @@ Panel* create_new_world_panel(Engine* engine, PagesControl* menu) {
auto folder = paths->getWorldsFolder()/u8path(nameutf8);
std::filesystem::create_directories(folder);
World* world = new World(nameutf8, folder, seed, settings);
auto screen = new LevelScreen(engine, world->create(settings, engine->getContent()));
Level* level = World::create(nameutf8, folder, seed, settings, engine->getContent());
auto screen = new LevelScreen(engine, level);
engine->setScreen(shared_ptr<Screen>(screen));
});
panel->add(button);

View File

@ -134,7 +134,7 @@ void LevelScreen::updateHotkeys() {
// TODO: remove in v0.16
if (Events::jpressed(keycode::F9)) {
blockid_t woodid = level->content->require("base:wood")->rt.id;
blockid_t woodid = level->content->requireBlock("base:wood")->rt.id;
for (size_t i = 0; i < level->chunks->volume; i++){
Chunk* chunk = level->chunks->chunks[i].get();
if (chunk) {

View File

@ -1,6 +1,5 @@
#include "ChunksController.h"
#include <iostream>
#include <limits.h>
#include <memory>
@ -57,7 +56,6 @@ void ChunksController::update(int64_t maxDuration) {
}
bool ChunksController::loadVisible(){
const Content* content = level->content;
const int w = chunks->w;
const int d = chunks->d;
const int ox = chunks->ox;
@ -115,16 +113,6 @@ bool ChunksController::loadVisible(){
chunk->updateHeights();
ContentIndices* indices = content->indices;
for (size_t i = 0; i < CHUNK_VOL; i++) {
blockid_t id = chunk->voxels[i].id;
if (indices->getBlockDef(id) == nullptr) {
std::cout << "corruped block detected at " << i << " of chunk ";
std::cout << chunk->x << "x" << chunk->z;
std::cout << " -> " << (int)id << std::endl;
chunk->voxels[i].id = 11;
}
}
if (!chunk->isLoadedLights()) {
lighting->prebuildSkyLight(chunk->x, chunk->z);
}

View File

@ -1,6 +1,7 @@
#include "ChunksStorage.h"
#include <assert.h>
#include <iostream>
#include "VoxelsVolume.h"
#include "Chunk.h"
@ -53,6 +54,18 @@ std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
chunk->setLoaded(true);
}
// Verifying and converting data
ContentIndices* indices = level->content->indices;
for (size_t i = 0; i < CHUNK_VOL; i++) {
blockid_t id = chunk->voxels[i].id;
if (indices->getBlockDef(id) == nullptr) {
std::cout << "corruped block detected at " << i << " of chunk ";
std::cout << chunk->x << "x" << chunk->z;
std::cout << " -> " << (int)id << std::endl;
chunk->voxels[i].id = 11;
}
}
light_t* lights = world->wfile->getLights(chunk->x, chunk->z);
if (lights) {
chunk->lightmap->set(lights);

View File

@ -97,16 +97,16 @@ float calc_height(fnl_state *noise, int real_x, int real_z){
}
WorldGenerator::WorldGenerator(const Content* content)
: idStone(content->require("base:stone")->rt.id),
idDirt(content->require("base:dirt")->rt.id),
idGrassBlock(content->require("base:grass_block")->rt.id),
idSand(content->require("base:sand")->rt.id),
idWater(content->require("base:water")->rt.id),
idWood(content->require("base:wood")->rt.id),
idLeaves(content->require("base:leaves")->rt.id),
idGrass(content->require("base:grass")->rt.id),
idFlower(content->require("base:flower")->rt.id),
idBazalt(content->require("base:bazalt")->rt.id) {;
: idStone(content->requireBlock("base:stone")->rt.id),
idDirt(content->requireBlock("base:dirt")->rt.id),
idGrassBlock(content->requireBlock("base:grass_block")->rt.id),
idSand(content->requireBlock("base:sand")->rt.id),
idWater(content->requireBlock("base:water")->rt.id),
idWood(content->requireBlock("base:wood")->rt.id),
idLeaves(content->requireBlock("base:leaves")->rt.id),
idGrass(content->requireBlock("base:grass")->rt.id),
idFlower(content->requireBlock("base:flower")->rt.id),
idBazalt(content->requireBlock("base:bazalt")->rt.id) {;
}
int generate_tree(fnl_state *noise,

View File

@ -6,6 +6,7 @@
#include "Level.h"
#include "../files/WorldFiles.h"
#include "../content/Content.h"
#include "../content/ContentIndexLUT.h"
#include "../voxels/Chunk.h"
#include "../voxels/Chunks.h"
#include "../voxels/ChunksStorage.h"
@ -13,15 +14,22 @@
#include "../window/Camera.h"
using glm::vec3;
using std::unique_ptr;
using std::shared_ptr;
using std::string;
using std::filesystem::path;
namespace fs = std::filesystem;
world_load_error::world_load_error(string message) : std::runtime_error(message) {
}
World::World(string name,
path directory,
uint64_t seed,
EngineSettings& settings)
EngineSettings& settings,
const Content* content)
: settings(settings),
content(content),
name(name),
seed(seed) {
wfile = new WorldFiles(directory, settings.debug);
@ -59,17 +67,39 @@ void World::write(Level* level) {
const float DEF_PLAYER_Y = 100.0f;
const float DEF_PLAYER_SPEED = 4.0f;
Level* World::create(EngineSettings& settings, const Content* content) {
Level* World::create(string name,
path directory,
uint64_t seed,
EngineSettings& settings,
const Content* content) {
World* world = new World(name, directory, seed, settings, content);
Player* player = new Player(vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED);
return new Level(this, content, player, settings);
return new Level(world, content, player, settings);
}
Level* World::load(EngineSettings& settings, const Content* content) {
wfile->readWorldInfo(this);
Level* World::load(path directory,
EngineSettings& settings,
const Content* content) {
path indicesFile = directory/path("indices.json");
if (fs::is_regular_file(indicesFile)) {
auto lut = ContentIndexLUT::create(indicesFile, content);
if (lut) {
throw world_load_error("world indices conflict");
}
}
unique_ptr<World> world (new World(".", directory, 0, settings, content));
auto& wfile = world->wfile;
if (!wfile->readWorldInfo(world.get())) {
throw world_load_error("could not to find world.json");
}
Player* player = new Player(vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED);
Level* level = new Level(this, content, player, settings);
Level* level = new Level(world.get(), content, player, settings);
wfile->readPlayer(player);
world.release();
return level;
}

View File

@ -3,6 +3,7 @@
#include <string>
#include <filesystem>
#include <stdexcept>
#include "../typedefs.h"
#include "../settings.h"
#include "../util/timeutil.h"
@ -13,8 +14,14 @@ class Chunks;
class Level;
class Player;
class world_load_error : public std::runtime_error {
public:
world_load_error(std::string message);
};
class World {
EngineSettings& settings;
const Content* const content;
public:
std::string name;
WorldFiles* wfile;
@ -30,13 +37,21 @@ public:
World(std::string name,
std::filesystem::path directory,
uint64_t seed,
EngineSettings& settings);
EngineSettings& settings,
const Content* content);
~World();
void updateTimers(float delta);
void write(Level* level);
Level* create(EngineSettings& settings, const Content* content);
Level* load(EngineSettings& settings, const Content* content);
static Level* create(std::string name,
std::filesystem::path directory,
uint64_t seed,
EngineSettings& settings,
const Content* content);
static Level* load(std::filesystem::path directory,
EngineSettings& settings,
const Content* content);
};
#endif /* WORLD_WORLD_H_ */