World indices check
This commit is contained in:
parent
551b230b94
commit
636cb0c44c
@ -64,7 +64,15 @@ Content::~Content() {
|
|||||||
delete indices;
|
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);
|
auto found = blockDefs.find(id);
|
||||||
if (found == blockDefs.end()) {
|
if (found == blockDefs.end()) {
|
||||||
throw std::runtime_error("missing block "+id);
|
throw std::runtime_error("missing block "+id);
|
||||||
|
|||||||
@ -55,7 +55,8 @@ public:
|
|||||||
std::unordered_map<std::string, Block*> blockDefs);
|
std::unordered_map<std::string, Block*> blockDefs);
|
||||||
~Content();
|
~Content();
|
||||||
|
|
||||||
Block* require(std::string id) const;
|
Block* findBlock(std::string id) const;
|
||||||
|
Block* requireBlock(std::string id) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONTENT_CONTENT_H_
|
#endif // CONTENT_CONTENT_H_
|
||||||
69
src/content/ContentIndexLUT.cpp
Normal file
69
src/content/ContentIndexLUT.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/content/ContentIndexLUT.h
Normal file
33
src/content/ContentIndexLUT.h
Normal 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_
|
||||||
@ -447,6 +447,7 @@ bool WorldFiles::readWorldInfo(World* world) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<json::JObject> root(files::read_json(file));
|
unique_ptr<json::JObject> root(files::read_json(file));
|
||||||
|
root->str("name", world->name);
|
||||||
root->num("seed", world->seed);
|
root->num("seed", world->seed);
|
||||||
|
|
||||||
json::JObject* verobj = root->obj("version");
|
json::JObject* verobj = root->obj("version");
|
||||||
|
|||||||
@ -56,9 +56,8 @@ Panel* create_main_menu_panel(Engine* engine, PagesControl* menu) {
|
|||||||
EngineSettings& settings = engine->getSettings();
|
EngineSettings& settings = engine->getSettings();
|
||||||
|
|
||||||
auto folder = paths->getWorldsFolder()/u8path(name);
|
auto folder = paths->getWorldsFolder()/u8path(name);
|
||||||
World* world = new World(name, folder, 42, settings);
|
Level* level = World::load(folder, settings, engine->getContent());
|
||||||
auto screen = new LevelScreen(engine,
|
auto screen = new LevelScreen(engine, level);
|
||||||
world->load(settings, engine->getContent()));
|
|
||||||
engine->setScreen(shared_ptr<Screen>(screen));
|
engine->setScreen(shared_ptr<Screen>(screen));
|
||||||
});
|
});
|
||||||
worldsPanel->add(button);
|
worldsPanel->add(button);
|
||||||
@ -146,8 +145,8 @@ Panel* create_new_world_panel(Engine* engine, PagesControl* menu) {
|
|||||||
|
|
||||||
auto folder = paths->getWorldsFolder()/u8path(nameutf8);
|
auto folder = paths->getWorldsFolder()/u8path(nameutf8);
|
||||||
std::filesystem::create_directories(folder);
|
std::filesystem::create_directories(folder);
|
||||||
World* world = new World(nameutf8, folder, seed, settings);
|
Level* level = World::create(nameutf8, folder, seed, settings, engine->getContent());
|
||||||
auto screen = new LevelScreen(engine, world->create(settings, engine->getContent()));
|
auto screen = new LevelScreen(engine, level);
|
||||||
engine->setScreen(shared_ptr<Screen>(screen));
|
engine->setScreen(shared_ptr<Screen>(screen));
|
||||||
});
|
});
|
||||||
panel->add(button);
|
panel->add(button);
|
||||||
|
|||||||
@ -134,7 +134,7 @@ void LevelScreen::updateHotkeys() {
|
|||||||
|
|
||||||
// TODO: remove in v0.16
|
// TODO: remove in v0.16
|
||||||
if (Events::jpressed(keycode::F9)) {
|
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++){
|
for (size_t i = 0; i < level->chunks->volume; i++){
|
||||||
Chunk* chunk = level->chunks->chunks[i].get();
|
Chunk* chunk = level->chunks->chunks[i].get();
|
||||||
if (chunk) {
|
if (chunk) {
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#include "ChunksController.h"
|
#include "ChunksController.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -57,7 +56,6 @@ void ChunksController::update(int64_t maxDuration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ChunksController::loadVisible(){
|
bool ChunksController::loadVisible(){
|
||||||
const Content* content = level->content;
|
|
||||||
const int w = chunks->w;
|
const int w = chunks->w;
|
||||||
const int d = chunks->d;
|
const int d = chunks->d;
|
||||||
const int ox = chunks->ox;
|
const int ox = chunks->ox;
|
||||||
@ -115,16 +113,6 @@ bool ChunksController::loadVisible(){
|
|||||||
|
|
||||||
chunk->updateHeights();
|
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()) {
|
if (!chunk->isLoadedLights()) {
|
||||||
lighting->prebuildSkyLight(chunk->x, chunk->z);
|
lighting->prebuildSkyLight(chunk->x, chunk->z);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "ChunksStorage.h"
|
#include "ChunksStorage.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "VoxelsVolume.h"
|
#include "VoxelsVolume.h"
|
||||||
#include "Chunk.h"
|
#include "Chunk.h"
|
||||||
@ -53,6 +54,18 @@ std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
|||||||
chunk->setLoaded(true);
|
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);
|
light_t* lights = world->wfile->getLights(chunk->x, chunk->z);
|
||||||
if (lights) {
|
if (lights) {
|
||||||
chunk->lightmap->set(lights);
|
chunk->lightmap->set(lights);
|
||||||
|
|||||||
@ -97,16 +97,16 @@ float calc_height(fnl_state *noise, int real_x, int real_z){
|
|||||||
}
|
}
|
||||||
|
|
||||||
WorldGenerator::WorldGenerator(const Content* content)
|
WorldGenerator::WorldGenerator(const Content* content)
|
||||||
: idStone(content->require("base:stone")->rt.id),
|
: idStone(content->requireBlock("base:stone")->rt.id),
|
||||||
idDirt(content->require("base:dirt")->rt.id),
|
idDirt(content->requireBlock("base:dirt")->rt.id),
|
||||||
idGrassBlock(content->require("base:grass_block")->rt.id),
|
idGrassBlock(content->requireBlock("base:grass_block")->rt.id),
|
||||||
idSand(content->require("base:sand")->rt.id),
|
idSand(content->requireBlock("base:sand")->rt.id),
|
||||||
idWater(content->require("base:water")->rt.id),
|
idWater(content->requireBlock("base:water")->rt.id),
|
||||||
idWood(content->require("base:wood")->rt.id),
|
idWood(content->requireBlock("base:wood")->rt.id),
|
||||||
idLeaves(content->require("base:leaves")->rt.id),
|
idLeaves(content->requireBlock("base:leaves")->rt.id),
|
||||||
idGrass(content->require("base:grass")->rt.id),
|
idGrass(content->requireBlock("base:grass")->rt.id),
|
||||||
idFlower(content->require("base:flower")->rt.id),
|
idFlower(content->requireBlock("base:flower")->rt.id),
|
||||||
idBazalt(content->require("base:bazalt")->rt.id) {;
|
idBazalt(content->requireBlock("base:bazalt")->rt.id) {;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generate_tree(fnl_state *noise,
|
int generate_tree(fnl_state *noise,
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include "Level.h"
|
#include "Level.h"
|
||||||
#include "../files/WorldFiles.h"
|
#include "../files/WorldFiles.h"
|
||||||
#include "../content/Content.h"
|
#include "../content/Content.h"
|
||||||
|
#include "../content/ContentIndexLUT.h"
|
||||||
#include "../voxels/Chunk.h"
|
#include "../voxels/Chunk.h"
|
||||||
#include "../voxels/Chunks.h"
|
#include "../voxels/Chunks.h"
|
||||||
#include "../voxels/ChunksStorage.h"
|
#include "../voxels/ChunksStorage.h"
|
||||||
@ -13,15 +14,22 @@
|
|||||||
#include "../window/Camera.h"
|
#include "../window/Camera.h"
|
||||||
|
|
||||||
using glm::vec3;
|
using glm::vec3;
|
||||||
|
using std::unique_ptr;
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::filesystem::path;
|
using std::filesystem::path;
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
world_load_error::world_load_error(string message) : std::runtime_error(message) {
|
||||||
|
}
|
||||||
|
|
||||||
World::World(string name,
|
World::World(string name,
|
||||||
path directory,
|
path directory,
|
||||||
uint64_t seed,
|
uint64_t seed,
|
||||||
EngineSettings& settings)
|
EngineSettings& settings,
|
||||||
|
const Content* content)
|
||||||
: settings(settings),
|
: settings(settings),
|
||||||
|
content(content),
|
||||||
name(name),
|
name(name),
|
||||||
seed(seed) {
|
seed(seed) {
|
||||||
wfile = new WorldFiles(directory, settings.debug);
|
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_Y = 100.0f;
|
||||||
const float DEF_PLAYER_SPEED = 4.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);
|
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) {
|
Level* World::load(path directory,
|
||||||
wfile->readWorldInfo(this);
|
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);
|
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);
|
wfile->readPlayer(player);
|
||||||
|
|
||||||
|
world.release();
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <stdexcept>
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../settings.h"
|
#include "../settings.h"
|
||||||
#include "../util/timeutil.h"
|
#include "../util/timeutil.h"
|
||||||
@ -13,8 +14,14 @@ class Chunks;
|
|||||||
class Level;
|
class Level;
|
||||||
class Player;
|
class Player;
|
||||||
|
|
||||||
|
class world_load_error : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
world_load_error(std::string message);
|
||||||
|
};
|
||||||
|
|
||||||
class World {
|
class World {
|
||||||
EngineSettings& settings;
|
EngineSettings& settings;
|
||||||
|
const Content* const content;
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
WorldFiles* wfile;
|
WorldFiles* wfile;
|
||||||
@ -30,13 +37,21 @@ public:
|
|||||||
World(std::string name,
|
World(std::string name,
|
||||||
std::filesystem::path directory,
|
std::filesystem::path directory,
|
||||||
uint64_t seed,
|
uint64_t seed,
|
||||||
EngineSettings& settings);
|
EngineSettings& settings,
|
||||||
|
const Content* content);
|
||||||
~World();
|
~World();
|
||||||
|
|
||||||
void updateTimers(float delta);
|
void updateTimers(float delta);
|
||||||
void write(Level* level);
|
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_ */
|
#endif /* WORLD_WORLD_H_ */
|
||||||
Loading…
x
Reference in New Issue
Block a user