diff --git a/res/textures/block.png b/res/textures/block.png index 8309b545..2879bd8f 100644 Binary files a/res/textures/block.png and b/res/textures/block.png differ diff --git a/src/constants.h b/src/constants.h index 97a3f4e7..e2665635 100644 --- a/src/constants.h +++ b/src/constants.h @@ -14,7 +14,7 @@ /* BLOCK_VOID is block id used to mark non-existing voxel (voxel of missing chunk) */ #define BLOCK_VOID (blockid_t)((2 << (sizeof(blockid_t)*CHAR_BIT)) - 1) -inline uint vox_index(int x, int y, int z, int w, int d) { +inline uint vox_index(int x, int y, int z, int w=CHUNK_W, int d=CHUNK_D) { return (y * d + z) * w + x; } diff --git a/src/content/Content.cpp b/src/content/Content.cpp new file mode 100644 index 00000000..0a1f88bc --- /dev/null +++ b/src/content/Content.cpp @@ -0,0 +1,50 @@ +#include "Content.h" + +#include + +#include "../voxels/Block.h" + +using std::vector; +using std::string; +using std::unordered_map; + +void ContentBuilder::add(Block* def) { + if (blockDefs.find(def->name) != blockDefs.end()) { + throw std::runtime_error("block name duplicate: "+def->name); + } + blockDefs[def->name] = def; + blockIds.push_back(def->name); +} + +Content* ContentBuilder::build() { + vector blockDefsIndices; + for (const string& name : blockIds) { + Block* def = blockDefs[name]; + def->id = blockDefsIndices.size(); + blockDefsIndices.push_back(def); + } + ContentIndices* indices = new ContentIndices(blockDefsIndices); + return new Content(indices, blockDefs); +} + +ContentIndices::ContentIndices(vector blockDefs) + : blockDefs(blockDefs) { +} + +Content::Content(ContentIndices* indices, + unordered_map blockDefs) + : blockDefs(blockDefs), + indices(indices) { +} + +Content::~Content() { + delete indices; +} + +Block* Content::require(std::string id) const { + auto found = blockDefs.find(id); + if (found == blockDefs.end()) { + throw std::runtime_error("missing block "+id); + } + return found->second; +} diff --git a/src/content/Content.h b/src/content/Content.h new file mode 100644 index 00000000..184d866d --- /dev/null +++ b/src/content/Content.h @@ -0,0 +1,57 @@ +#ifndef CONTENT_CONTENT_H_ +#define CONTENT_CONTENT_H_ + +#include +#include +#include +#include "../typedefs.h" + +class Block; +class Content; + +class ContentBuilder { + std::unordered_map blockDefs; + std::vector blockIds; +public: + void add(Block* def); + + Content* build(); +}; + +/* Runtime defs cache: indices */ +class ContentIndices { + // blockDefs must be a plain vector with block id used as index + std::vector blockDefs; +public: + ContentIndices(std::vector blockDefs); + + inline Block* getBlockDef(blockid_t id) const { + if (id >= blockDefs.size()) + return nullptr; + return blockDefs[id]; + } + + inline size_t countBlockDefs() const { + return blockDefs.size(); + } + + // use this for critical spots to prevent range check overhead + const Block* const* getBlockDefs() const { + return blockDefs.data(); + } +}; + +/* Content is a definitions repository */ +class Content { + std::unordered_map blockDefs; +public: + ContentIndices* const indices; + + Content(ContentIndices* indices, + std::unordered_map blockDefs); + ~Content(); + + Block* require(std::string id) const; +}; + +#endif // CONTENT_CONTENT_H_ \ No newline at end of file diff --git a/src/definitions.cpp b/src/definitions.cpp index d0112e48..eb4e68dd 100644 --- a/src/definitions.cpp +++ b/src/definitions.cpp @@ -1,97 +1,95 @@ #include "definitions.h" +#include "content/Content.h" #include "window/Window.h" #include "window/Events.h" #include "window/input.h" #include "voxels/Block.h" // All in-game definitions (blocks, items, etc..) -void setup_definitions() { - for (size_t i = 0; i < 256; i++) { - Block::blocks[i] = nullptr; - } - - Block* block = new Block(BLOCK_AIR, 0); +void setup_definitions(ContentBuilder* builder) { + // TODO: automatic atlas generation instead of using texture indices + Block* block = new Block("core:air", 0); block->drawGroup = 1; block->lightPassing = true; block->skyLightPassing = true; block->obstacle = false; block->selectable = false; block->model = BlockModel::none; - Block::blocks[block->id] = block; + builder->add(block); - block = new Block(BLOCK_DIRT, 2); - Block::blocks[block->id] = block; + block = new Block("base:dirt", 2); + builder->add(block); - block = new Block(BLOCK_GRASS_BLOCK, 4); + block = new Block("base:grass_block", 4); block->textureFaces[2] = 2; block->textureFaces[3] = 1; - Block::blocks[block->id] = block; + builder->add(block); - block = new Block(BLOCK_LAMP, 3); + block = new Block("base:lamp", 3); block->emission[0] = 15; block->emission[1] = 14; block->emission[2] = 13; - Block::blocks[block->id] = block; + builder->add(block); - block = new Block(BLOCK_GLASS,5); + block = new Block("base:glass",5); block->drawGroup = 2; block->lightPassing = true; - Block::blocks[block->id] = block; + builder->add(block); - block = new Block(BLOCK_PLANKS, 6); - Block::blocks[block->id] = block; + block = new Block("base:planks", 6); + builder->add(block); - block = new Block(BLOCK_WOOD, 7); + block = new Block("base:wood", 7); block->textureFaces[2] = 8; block->textureFaces[3] = 8; block->rotatable = true; - Block::blocks[block->id] = block; + builder->add(block); - block = new Block(BLOCK_LEAVES, 9); - Block::blocks[block->id] = block; + block = new Block("base:leaves", 9); + builder->add(block); - block = new Block(BLOCK_STONE, 10); - Block::blocks[block->id] = block; + block = new Block("base:stone", 10); + builder->add(block); - block = new Block(BLOCK_WATER, 11); + block = new Block("base:water", 11); block->drawGroup = 4; block->lightPassing = true; block->skyLightPassing = false; block->obstacle = false; block->selectable = false; - Block::blocks[block->id] = block; + builder->add(block); - block = new Block(BLOCK_SAND, 12); - Block::blocks[block->id] = block; + block = new Block("base:sand", 12); + builder->add(block); - block = new Block(BLOCK_BEDROCK, 13); + block = new Block("base:bedrock", 13); block->breakable = false; - Block::blocks[block->id] = block; + builder->add(block); - block = new Block(BLOCK_GRASS, 14); + block = new Block("base:grass", 14); block->drawGroup = 5; block->lightPassing = true; block->obstacle = false; block->model = BlockModel::xsprite; block->hitboxScale = 0.5f; - Block::blocks[block->id] = block; + builder->add(block); - block = new Block(BLOCK_FLOWER, 16); + block = new Block("base:flower", 16); block->drawGroup = 5; block->lightPassing = true; block->obstacle = false; block->model = BlockModel::xsprite; - Block::blocks[block->id] = block; + builder->add(block); - block = new Block(BLOCK_BRICK, 17); - Block::blocks[block->id] = block; + block = new Block("base:brick", 17); + builder->add(block); - block = new Block(BLOCK_METAL, 18); - Block::blocks[block->id] = block; + block = new Block("base:metal", 18); + builder->add(block); - block = new Block(BLOCK_RUST, 19); - Block::blocks[block->id] = block; + block = new Block("base:rust", 19); + builder->add(block); } void setup_bindings() { diff --git a/src/definitions.h b/src/definitions.h index c4b5e0ba..31dc982c 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -4,25 +4,10 @@ #include #include "core_defs.h" -#define BLOCK_DIRT 1 -#define BLOCK_GRASS_BLOCK 2 -#define BLOCK_LAMP 3 -#define BLOCK_GLASS 4 -#define BLOCK_PLANKS 5 -#define BLOCK_WOOD 6 -#define BLOCK_LEAVES 7 -#define BLOCK_STONE 8 -#define BLOCK_WATER 9 -#define BLOCK_SAND 10 -#define BLOCK_BEDROCK 11 -#define BLOCK_GRASS 12 -#define BLOCK_FLOWER 13 -#define BLOCK_BRICK 14 -#define BLOCK_METAL 15 -#define BLOCK_RUST 16 +class ContentBuilder; extern void setup_bindings(); -extern void setup_definitions(); +extern void setup_definitions(ContentBuilder* builder); #endif // DECLARATIONS_H diff --git a/src/engine.cpp b/src/engine.cpp index 572db177..3f0e014e 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -41,7 +41,8 @@ using std::filesystem::path; using glm::vec3; using gui::GUI; -Engine::Engine(EngineSettings& settings) : settings(settings) { +Engine::Engine(EngineSettings& settings, Content* content) + : settings(settings), content(content) { Window::initialize(settings.display); assets = new Assets(); @@ -128,4 +129,8 @@ Assets* Engine::getAssets() { void Engine::setScreen(shared_ptr screen) { this->screen = screen; +} + +const Content* Engine::getContent() const { + return content; } \ No newline at end of file diff --git a/src/engine.h b/src/engine.h index 76c56ee3..879cc948 100644 --- a/src/engine.h +++ b/src/engine.h @@ -10,6 +10,7 @@ class Assets; class Level; class Screen; +class Content; namespace gui { class GUI; @@ -24,6 +25,7 @@ class Engine { Assets* assets; std::shared_ptr screen = nullptr; EngineSettings& settings; + Content* content; uint64_t frame = 0; double lastTime = 0.0; @@ -31,7 +33,7 @@ class Engine { gui::GUI* gui; public: - Engine(EngineSettings& settings); + Engine(EngineSettings& settings, Content* content); ~Engine(); void updateTimers(); @@ -42,6 +44,8 @@ public: gui::GUI* getGUI(); EngineSettings& getSettings(); void setScreen(std::shared_ptr screen); + + const Content* getContent() const; }; #endif // SRC_ENGINE_H_ \ No newline at end of file diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp new file mode 100644 index 00000000..fff17c1b --- /dev/null +++ b/src/files/settings_io.cpp @@ -0,0 +1,77 @@ +#include "settings_io.h" + +#include + +#include "../window/Events.h" +#include "../window/input.h" + +#include "../coders/json.h" + +using std::string; + +toml::Wrapper create_wrapper(EngineSettings& settings) { + toml::Wrapper wrapper; + toml::Section& display = wrapper.add("display"); + display.add("width", &settings.display.width); + display.add("height", &settings.display.height); + display.add("samples", &settings.display.samples); + display.add("swap-interval", &settings.display.swapInterval); + + toml::Section& chunks = wrapper.add("chunks"); + chunks.add("load-distance", &settings.chunks.loadDistance); + chunks.add("load-speed", &settings.chunks.loadSpeed); + chunks.add("padding", &settings.chunks.padding); + + toml::Section& camera = wrapper.add("camera"); + camera.add("fov-effects", &settings.camera.fovEvents); + camera.add("shaking", &settings.camera.shaking); + + toml::Section& graphics = wrapper.add("graphics"); + graphics.add("fog-curve", &settings.graphics.fogCurve); + + toml::Section& debug = wrapper.add("debug"); + debug.add("generator-test-mode", &settings.debug.generatorTestMode); + return wrapper; +} + +string write_controls() { + json::JObject* obj = new json::JObject(); + for (auto& entry : Events::bindings) { + const auto& binding = entry.second; + + json::JObject* jentry = new json::JObject(); + switch (binding.type) { + case inputtype::keyboard: jentry->put("type", "keyboard"); break; + case inputtype::mouse: jentry->put("type", "mouse"); break; + default: throw std::runtime_error("unsupported control type"); + } + jentry->put("code", binding.code); + obj->put(entry.first, jentry); + } + return json::stringify(obj, true, " "); +} + +void load_controls(string filename, string source) { + json::JObject* obj = json::parse(filename, source); + for (auto& entry : Events::bindings) { + auto& binding = entry.second; + + json::JObject* jentry = obj->obj(entry.first); + if (jentry == nullptr) + continue; + inputtype type; + string typestr; + jentry->str("type", typestr); + + if (typestr == "keyboard") { + type = inputtype::keyboard; + } else if (typestr == "mouse") { + type = inputtype::mouse; + } else { + std::cerr << "unknown input type '" << typestr << "'" << std::endl; + continue; + } + binding.type = type; + jentry->num("code", binding.code); + } +} \ No newline at end of file diff --git a/src/files/settings_io.h b/src/files/settings_io.h new file mode 100644 index 00000000..e40a6daa --- /dev/null +++ b/src/files/settings_io.h @@ -0,0 +1,12 @@ +#ifndef FILES_SETTINGS_IO_H_ +#define FILES_SETTINGS_IO_H_ + +#include +#include "../coders/toml.h" +#include "../settings.h" + +extern std::string write_controls(); +extern toml::Wrapper create_wrapper(EngineSettings& settings); +extern void load_controls(std::string filename, std::string source); + +#endif // FILES_SETTINGS_IO_H_ \ No newline at end of file diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index d22eacae..42d3b145 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -3,11 +3,13 @@ #include #include #include +#include #include #include #include #include "../typedefs.h" +#include "../content/Content.h" #include "../util/stringutil.h" #include "../assets/Assets.h" #include "../graphics/Shader.h" @@ -24,6 +26,7 @@ #include "../world/Level.h" #include "../objects/Player.h" #include "../physics/Hitbox.h" +#include "../maths/voxmaths.h" #include "gui/controls.h" #include "gui/panels.h" #include "gui/UINode.h" @@ -45,7 +48,10 @@ inline Label* create_label(gui::wstringsupplier supplier) { return label; } -HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(engine->getAssets()), gui(engine->getGUI()) { +HudRenderer::HudRenderer(Engine* engine, Level* level) + : level(level), + assets(engine->getAssets()), + gui(engine->getGUI()) { auto menu = gui->getMenu(); batch = new Batch2D(1024); uicamera = new Camera(vec3(), 1); @@ -93,7 +99,7 @@ HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(en str[0] += ax; Label* label = new Label(str); label->margin(vec4(2, 3, 2, 3)); - sub->add(shared_ptr(label)); + sub->add(label); sub->color(vec4(0.0f)); // Coord input @@ -111,8 +117,8 @@ HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(en } }); - sub->add(shared_ptr(box)); - panel->add(shared_ptr(sub)); + sub->add(box); + panel->add(sub); } panel->refresh(); menu->reset(); @@ -133,68 +139,46 @@ void HudRenderer::drawDebug(int fps, bool occlusion){ fpsMax = max(fps, fpsMax); } -void HudRenderer::drawInventory(const GfxContext& ctx, Player* player) { +/* Inventory temporary replaced with blocks access panel */ +void HudRenderer::drawContentAccess(const GfxContext& ctx, Player* player) { + const Content* content = level->content; + const ContentIndices* contentIds = content->indices; + const Viewport& viewport = ctx.getViewport(); const uint width = viewport.getWidth(); - const uint height = viewport.getHeight(); - Texture* blocks = assets->getTexture("block_tex"); - uint size = 48; - uint step = 64; - uint inv_cols = 10; - uint inv_rows = 8; - uint inv_w = step*inv_cols + size; - uint inv_h = step*inv_rows + size; - int inv_x = (width - (inv_w)) / 2; - int inv_y = (height - (inv_h)) / 2; - int xs = (width - inv_w + step)/2; - int ys = (height - inv_h + step)/2; - if (width > inv_w*3){ - inv_x = (width + (inv_w)) / 2; - inv_y = (height - (inv_h)) / 2; - xs = (width + inv_w + step)/2; - ys = (height - inv_h + step)/2; - } + uint count = contentIds->countBlockDefs(); + uint icon_size = 48; + uint interval = 4; + uint inv_cols = 8; + uint inv_rows = ceildiv(count-1, inv_cols); + int pad_x = interval; + int pad_y = interval; + uint inv_w = inv_cols * icon_size + (inv_cols-1) * interval + pad_x * 2; + uint inv_h = inv_rows * icon_size + (inv_rows-1) * interval + pad_x * 2; + int inv_x = (width - (inv_w)); + int inv_y = 0; + int xs = inv_x + pad_x; + int ys = inv_y + pad_y; + vec4 tint = vec4(1.0f); int mx = Events::x; int my = Events::y; - uint count = inv_cols * inv_rows; - // back + // background batch->texture(nullptr); - batch->color = vec4(0.0f, 0.0f, 0.0f, 0.3f); - batch->rect(inv_x - 4, inv_y - 4, inv_w+8, inv_h+8, - 0.95f, 0.95f, 0.95f, 0.85f, 0.85f, 0.85f, - 0.7f, 0.7f, 0.7f, - 0.55f, 0.55f, 0.55f, 0.45f, 0.45f, 0.45f, 4); - batch->rect(inv_x, inv_y, inv_w, inv_h, - 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, - 0.75f, 0.75f, 0.75f, - 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 4); + batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f); + batch->rect(inv_x, inv_y, inv_w, inv_h); - batch->color = vec4(0.35f, 0.35f, 0.35f, 1.0f); - for (uint i = 0; i < count; i++) { - int x = xs + step * (i % (inv_cols)); - int y = ys + step * (i / (inv_cols)); - batch->rect(x-2, y-2, size+4, size+4, - 0.45f, 0.45f, 0.45f, 0.55f, 0.55f, 0.55f, - 0.7f, 0.7f, 0.7f, - 0.85f, 0.85f, 0.85f, 0.95f, 0.95f, 0.95f, 2); - batch->rect(x, y, size, size, - 0.65f, 0.65f, 0.65f, 0.65f, 0.65f, 0.65f, - 0.65f, 0.65f, 0.65f, - 0.65f, 0.65f, 0.65f, 0.65f, 0.65f, 0.65f, 2); - } - - // front - batch->texture(blocks); - for (uint i = 0; i < count; i++) { - Block* cblock = Block::blocks[i+1]; + // blocks & items + batch->texture(assets->getTexture("block_tex")); + for (uint i = 0; i < count-1; i++) { + Block* cblock = contentIds->getBlockDef(i+1); if (cblock == nullptr) break; - int x = xs + step * (i % inv_cols); - int y = ys + step * (i / inv_cols); - if (mx > x && mx < x + (int)size && my > y && my < y + (int)size) { + int x = xs + (icon_size+interval) * (i % inv_cols); + int y = ys + (icon_size+interval) * (i / inv_cols); + if (mx > x && mx < x + (int)icon_size && my > y && my < y + (int)icon_size) { tint.r *= 1.2f; tint.g *= 1.2f; tint.b *= 1.2f; @@ -206,9 +190,9 @@ void HudRenderer::drawInventory(const GfxContext& ctx, Player* player) { } if (cblock->model == BlockModel::block){ - batch->blockSprite(x, y, size, size, 16, cblock->textureFaces, tint); + batch->blockSprite(x, y, icon_size, icon_size, 16, cblock->textureFaces, tint); } else if (cblock->model == BlockModel::xsprite){ - batch->sprite(x, y, size, size, 16, cblock->textureFaces[3], tint); + batch->sprite(x, y, icon_size, icon_size, 16, cblock->textureFaces[3], tint); } } } @@ -234,11 +218,15 @@ void HudRenderer::update() { inventoryOpen = !inventoryOpen; } } - if ((pause || inventoryOpen) == Events::_cursor_locked) + if ((pause || inventoryOpen) == Events::_cursor_locked) { Events::toggleCursor(); + } } void HudRenderer::draw(const GfxContext& ctx){ + const Content* content = level->content; + const ContentIndices* contentIds = content->indices; + const Viewport& viewport = ctx.getViewport(); const uint width = viewport.getWidth(); const uint height = viewport.getHeight(); @@ -265,31 +253,19 @@ void HudRenderer::draw(const GfxContext& ctx){ } Player* player = level->player; - batch->rect(width/2-128-4, height-80-4, 256+8, 64+8, - 0.95f, 0.95f, 0.95f, 0.85f, 0.85f, 0.85f, - 0.7f, 0.7f, 0.7f, - 0.55f, 0.55f, 0.55f, 0.45f, 0.45f, 0.45f, 4); - batch->rect(width/2-128, height - 80, 256, 64, - 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, - 0.75f, 0.75f, 0.75f, - 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 4); - batch->rect(width/2-32+2, height - 80+2, 60, 60, - 0.45f, 0.45f, 0.45f, 0.55f, 0.55f, 0.55f, - 0.7f, 0.7f, 0.7f, - 0.85f, 0.85f, 0.85f, 0.95f, 0.95f, 0.95f, 2); - batch->rect(width/2-32+4, height - 80+4, 56, 56, - 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, - 0.75f, 0.75f, 0.75f, - 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 2); + batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f); + batch->rect(width - 68, height - 68, 68, 68); + + batch->color = vec4(1.0f); batch->texture(blocks); - { - Block* cblock = Block::blocks[player->choosenBlock]; + Block* cblock = contentIds->getBlockDef(player->choosenBlock); + assert(cblock != nullptr); if (cblock->model == BlockModel::block){ - batch->blockSprite(width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces, vec4(1.0f)); + batch->blockSprite(width-56, uicamera->fov - 56, 48, 48, 16, cblock->textureFaces, vec4(1.0f)); } else if (cblock->model == BlockModel::xsprite){ - batch->sprite(width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f)); + batch->sprite(width-56, uicamera->fov - 56, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f)); } } @@ -299,7 +275,7 @@ void HudRenderer::draw(const GfxContext& ctx){ batch->rect(0, 0, width, height); } if (inventoryOpen) { - drawInventory(ctx, player); + drawContentAccess(ctx, player); } batch->render(); } diff --git a/src/frontend/hud.h b/src/frontend/hud.h index 2da61830..68f1d668 100644 --- a/src/frontend/hud.h +++ b/src/frontend/hud.h @@ -40,7 +40,7 @@ public: ~HudRenderer(); void update(); - void drawInventory(const GfxContext& ctx, Player* player); + void drawContentAccess(const GfxContext& ctx, Player* player); void draw(const GfxContext& context); void drawDebug(int fps, bool occlusion); diff --git a/src/frontend/menu.cpp b/src/frontend/menu.cpp index f014f4a9..b1361599 100644 --- a/src/frontend/menu.cpp +++ b/src/frontend/menu.cpp @@ -60,7 +60,8 @@ Panel* create_main_menu_panel(Engine* engine, PagesControl* menu) { auto folder = enginefs::get_worlds_folder()/u8path(name); World* world = new World(name, folder, 42, settings); - auto screen = new LevelScreen(engine, world->load(settings)); + auto screen = new LevelScreen(engine, + world->load(settings, engine->getContent())); engine->setScreen(shared_ptr(screen)); }); worldsPanel->add(button); @@ -148,7 +149,7 @@ Panel* create_new_world_panel(Engine* engine, PagesControl* menu) { auto folder = enginefs::get_worlds_folder()/u8path(nameutf8); std::filesystem::create_directories(folder); World* world = new World(nameutf8, folder, seed, settings); - auto screen = new LevelScreen(engine, world->load(settings)); + auto screen = new LevelScreen(engine, world->load(settings, engine->getContent())); engine->setScreen(shared_ptr(screen)); }); panel->add(button); diff --git a/src/frontend/world_render.cpp b/src/frontend/world_render.cpp index 5e102287..c06649ec 100644 --- a/src/frontend/world_render.cpp +++ b/src/frontend/world_render.cpp @@ -3,7 +3,9 @@ #include #include #include +#include +#include "../content/Content.h" #include "../graphics/ChunksRenderer.h" #include "../window/Window.h" #include "../window/Camera.h" @@ -94,6 +96,8 @@ void WorldRenderer::drawChunks(Chunks* chunks, void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion){ + const Content* content = level->content; + const ContentIndices* contentIds = content->indices; Assets* assets = engine->getAssets(); Texture* texture = assets->getTexture("block"); Shader* shader = assets->getShader("main"); @@ -127,7 +131,8 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion) shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); shader->uniform3f("u_cameraPos", camera->position); - Block* cblock = Block::blocks[level->player->choosenBlock]; + Block* cblock = contentIds->getBlockDef(level->player->choosenBlock); + assert(cblock != nullptr); float multiplier = 0.5f; shader->uniform3f("u_torchlightColor", cblock->emission[0] / 15.0f * multiplier, @@ -142,7 +147,8 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion) shader->uniformMatrix("u_model", mat4(1.0f)); if (level->playerController->selectedBlockId != -1){ - Block* block = Block::blocks[level->playerController->selectedBlockId]; + Block* block = contentIds->getBlockDef(level->playerController->selectedBlockId); + assert(block != nullptr); vec3 pos = level->playerController->selectedBlockPosition; linesShader->use(); linesShader->uniformMatrix("u_projview", camera->getProjView()); diff --git a/src/graphics/BlocksRenderer.cpp b/src/graphics/BlocksRenderer.cpp index af421a01..6dae363a 100644 --- a/src/graphics/BlocksRenderer.cpp +++ b/src/graphics/BlocksRenderer.cpp @@ -5,6 +5,7 @@ #include "Mesh.h" #include "UVRegion.h" #include "../constants.h" +#include "../content/Content.h" #include "../voxels/Block.h" #include "../voxels/Chunk.h" #include "../voxels/VoxelsVolume.h" @@ -17,10 +18,16 @@ using glm::vec4; #define VERTEX_SIZE 9 -BlocksRenderer::BlocksRenderer(size_t capacity) : vertexOffset(0), indexOffset(0), indexSize(0), capacity(capacity) { +BlocksRenderer::BlocksRenderer(size_t capacity, const Content* content) + : content(content), + vertexOffset(0), + indexOffset(0), + indexSize(0), + capacity(capacity) { vertexBuffer = new float[capacity]; indexBuffer = new int[capacity]; voxelsBuffer = new VoxelsVolume(CHUNK_W + 2, CHUNK_H, CHUNK_D + 2); + blockDefsCache = content->indices->getBlockDefs(); } BlocksRenderer::~BlocksRenderer() { @@ -256,7 +263,7 @@ bool BlocksRenderer::isOpen(int x, int y, int z, ubyte group) const { blockid_t id = voxelsBuffer->pickBlockId(chunk->x * CHUNK_W + x, y, chunk->z * CHUNK_D + z); if (id == BLOCK_VOID) return false; - const Block& block = *Block::blocks[id]; + const Block& block = *blockDefsCache[id]; if (block.drawGroup != group && block.lightPassing) { return true; } @@ -267,7 +274,7 @@ bool BlocksRenderer::isOpenForLight(int x, int y, int z) const { blockid_t id = voxelsBuffer->pickBlockId(chunk->x * CHUNK_W + x, y, chunk->z * CHUNK_D + z); if (id == BLOCK_VOID) return false; - const Block& block = *Block::blocks[id]; + const Block& block = *blockDefsCache[id]; if (block.lightPassing) { return true; } @@ -311,7 +318,7 @@ void BlocksRenderer::render(const voxel* voxels, int atlas_size) { for (int i = begin; i < end; i++) { const voxel& vox = voxels[i]; blockid_t id = vox.id; - const Block& def = *Block::blocks[id]; + const Block& def = *blockDefsCache[id]; if (!id || def.drawGroup != group) continue; const UVRegion texfaces[6]{ uvfor(def, 0, atlas_size), uvfor(def, 1, atlas_size), diff --git a/src/graphics/BlocksRenderer.h b/src/graphics/BlocksRenderer.h index 03c0d412..3c956d41 100644 --- a/src/graphics/BlocksRenderer.h +++ b/src/graphics/BlocksRenderer.h @@ -7,6 +7,7 @@ #include "../typedefs.h" #include "../voxels/voxel.h" +class Content; class Mesh; class Block; class Chunk; @@ -15,6 +16,7 @@ class VoxelsVolume; class ChunksStorage; class BlocksRenderer { + const Content* const content; float* vertexBuffer; int* indexBuffer; size_t vertexOffset; @@ -26,6 +28,8 @@ class BlocksRenderer { const Chunk* chunk = nullptr; VoxelsVolume* voxelsBuffer; + const Block* const* blockDefsCache; + void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light); void index(int a, int b, int c, int d, int e, int f); @@ -64,7 +68,7 @@ class BlocksRenderer { glm::vec4 pickSoftLight(int x, int y, int z, const glm::ivec3& right, const glm::ivec3& up) const; void render(const voxel* voxels, int atlas_size); public: - BlocksRenderer(size_t capacity); + BlocksRenderer(size_t capacity, const Content* content); virtual ~BlocksRenderer(); Mesh* render(const Chunk* chunk, int atlas_size, const ChunksStorage* chunks); diff --git a/src/graphics/ChunksRenderer.cpp b/src/graphics/ChunksRenderer.cpp index a74550c8..2e14a496 100644 --- a/src/graphics/ChunksRenderer.cpp +++ b/src/graphics/ChunksRenderer.cpp @@ -13,7 +13,7 @@ using std::shared_ptr; ChunksRenderer::ChunksRenderer(Level* level) : level(level) { const int MAX_FULL_CUBES = 3000; - renderer = new BlocksRenderer(9 * 6 * 6 * MAX_FULL_CUBES); + renderer = new BlocksRenderer(9 * 6 * 6 * MAX_FULL_CUBES, level->content); } ChunksRenderer::~ChunksRenderer() { diff --git a/src/lighting/LightSolver.cpp b/src/lighting/LightSolver.cpp index 07070a05..f6c53442 100644 --- a/src/lighting/LightSolver.cpp +++ b/src/lighting/LightSolver.cpp @@ -2,12 +2,14 @@ #include #include "LightSolver.h" #include "Lightmap.h" +#include "../content/Content.h" #include "../voxels/Chunks.h" #include "../voxels/Chunk.h" #include "../voxels/voxel.h" #include "../voxels/Block.h" -LightSolver::LightSolver(Chunks* chunks, int channel) : chunks(chunks), channel(channel) { +LightSolver::LightSolver(const ContentIndices* contentIds, Chunks* chunks, int channel) + : contentIds(contentIds), chunks(chunks), channel(channel) { } void LightSolver::add(int x, int y, int z, int emission) { @@ -93,6 +95,7 @@ void LightSolver::solve(){ } } + const Block* const* blockDefs = contentIds->getBlockDefs(); while (!addqueue.empty()){ const lightentry entry = addqueue.front(); addqueue.pop(); @@ -108,7 +111,7 @@ void LightSolver::solve(){ if (chunk) { int light = chunks->getLight(x,y,z, channel); voxel* v = chunks->get(x,y,z); - Block* block = Block::blocks[v->id]; + const Block* block = blockDefs[v->id]; if (block->lightPassing && light+2 <= entry.light){ chunk->lightmap->set(x-chunk->x*CHUNK_W, y, z-chunk->z*CHUNK_D, channel, entry.light-1); chunk->setModified(true); diff --git a/src/lighting/LightSolver.h b/src/lighting/LightSolver.h index 4ef8fa3f..25648ced 100644 --- a/src/lighting/LightSolver.h +++ b/src/lighting/LightSolver.h @@ -4,6 +4,7 @@ #include class Chunks; +class ContentIndices; struct lightentry { int x; @@ -15,10 +16,11 @@ struct lightentry { class LightSolver { std::queue addqueue; std::queue remqueue; + const ContentIndices* const contentIds; Chunks* chunks; int channel; public: - LightSolver(Chunks* chunks, int channel); + LightSolver(const ContentIndices* contentIds, Chunks* chunks, int channel); void add(int x, int y, int z); void add(int x, int y, int z, int emission); diff --git a/src/lighting/Lighting.cpp b/src/lighting/Lighting.cpp index f4d884e8..568bfe9f 100644 --- a/src/lighting/Lighting.cpp +++ b/src/lighting/Lighting.cpp @@ -1,22 +1,25 @@ #include "Lighting.h" #include "LightSolver.h" #include "Lightmap.h" +#include "../content/Content.h" #include "../voxels/Chunks.h" #include "../voxels/Chunk.h" #include "../voxels/voxel.h" #include "../voxels/Block.h" +#include "../constants.h" #include #include using std::shared_ptr; -Lighting::Lighting(Chunks* chunks){ - this->chunks = chunks; - solverR = new LightSolver(chunks, 0); - solverG = new LightSolver(chunks, 1); - solverB = new LightSolver(chunks, 2); - solverS = new LightSolver(chunks, 3); +Lighting::Lighting(const Content* content, Chunks* chunks) + : content(content), chunks(chunks) { + const ContentIndices* contentIds = content->indices; + solverR = new LightSolver(contentIds, chunks, 0); + solverG = new LightSolver(contentIds, chunks, 1); + solverB = new LightSolver(contentIds, chunks, 2); + solverS = new LightSolver(contentIds, chunks, 3); } Lighting::~Lighting(){ @@ -39,6 +42,8 @@ void Lighting::clear(){ } void Lighting::prebuildSkyLight(int cx, int cz){ + const Block* const* blockDefs = content->indices->getBlockDefs(); + Chunk* chunk = chunks->getChunk(cx, cz); int highestPoint = 0; for (int z = 0; z < CHUNK_D; z++){ @@ -47,7 +52,7 @@ void Lighting::prebuildSkyLight(int cx, int cz){ if (y < 0) break; voxel* vox = &(chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]); - Block* block = Block::blocks[vox->id]; + const Block* block = blockDefs[vox->id]; if (!block->skyLightPassing) { if (highestPoint < y) highestPoint = y; @@ -63,13 +68,15 @@ void Lighting::prebuildSkyLight(int cx, int cz){ } void Lighting::buildSkyLight(int cx, int cz){ + const Block* const* blockDefs = content->indices->getBlockDefs(); + Chunk* chunk = chunks->getChunk(cx, cz); for (int z = 0; z < CHUNK_D; z++){ for (int x = 0; x < CHUNK_W; x++){ for (int y = chunk->lightmap->highestPoint; y >= 0; y--){ int gx = x + cx * CHUNK_W; int gz = z + cz * CHUNK_D; - while (y > 0 && !Block::blocks[chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x].id]->lightPassing) { + while (y > 0 && !blockDefs[chunk->voxels[vox_index(x, y, z)].id]->lightPassing) { y--; } if (chunk->lightmap->getS(x, y, z) != 15) { @@ -88,13 +95,14 @@ void Lighting::buildSkyLight(int cx, int cz){ } void Lighting::onChunkLoaded(int cx, int cz){ + const Block* const* blockDefs = content->indices->getBlockDefs(); const Chunk* chunk = chunks->getChunk(cx, cz); for (unsigned int y = 0; y < CHUNK_H; y++){ for (unsigned int z = 0; z < CHUNK_D; z++){ for (unsigned int x = 0; x < CHUNK_W; x++){ voxel vox = chunk->voxels[(y * CHUNK_D + z) * CHUNK_W + x]; - Block* block = Block::blocks[vox.id]; + const Block* block = blockDefs[vox.id]; int gx = x + cx * CHUNK_W; int gz = z + cz * CHUNK_D; if (block->emission[0] || block->emission[1] || block->emission[2]){ @@ -128,8 +136,8 @@ void Lighting::onChunkLoaded(int cx, int cz){ solverS->solve(); } -void Lighting::onBlockSet(int x, int y, int z, int id){ - Block* block = Block::blocks[id]; +void Lighting::onBlockSet(int x, int y, int z, int const id){ + Block* block = content->indices->getBlockDef(id); if (id == 0){ solverR->remove(x,y,z); solverG->remove(x,y,z); @@ -140,7 +148,7 @@ void Lighting::onBlockSet(int x, int y, int z, int id){ if (chunks->getLight(x,y+1,z, 3) == 0xF){ for (int i = y; i >= 0; i--){ voxel* vox = chunks->get(x,i,z); - if ((vox == nullptr || vox->id != 0) && Block::blocks[id]->skyLightPassing) + if ((vox == nullptr || vox->id != 0) && block->skyLightPassing) break; solverS->add(x,i,z, 0xF); } diff --git a/src/lighting/Lighting.h b/src/lighting/Lighting.h index e1caf777..dbec1033 100644 --- a/src/lighting/Lighting.h +++ b/src/lighting/Lighting.h @@ -1,17 +1,19 @@ #ifndef LIGHTING_LIGHTING_H_ #define LIGHTING_LIGHTING_H_ +class Content; class Chunks; class LightSolver; class Lighting { - Chunks* chunks = nullptr; - LightSolver* solverR = nullptr; - LightSolver* solverG = nullptr; - LightSolver* solverB = nullptr; - LightSolver* solverS = nullptr; + const Content* const content; + Chunks* chunks; + LightSolver* solverR; + LightSolver* solverG; + LightSolver* solverB; + LightSolver* solverS; public: - Lighting(Chunks* chunks); + Lighting(const Content* content, Chunks* chunks); ~Lighting(); void clear(); diff --git a/src/objects/player_control.cpp b/src/objects/player_control.cpp index 0c426164..fac74e19 100644 --- a/src/objects/player_control.cpp +++ b/src/objects/player_control.cpp @@ -5,6 +5,7 @@ #include "../physics/Hitbox.h" #include "../lighting/Lighting.h" #include "../world/Level.h" +#include "../content/Content.h" #include "../voxels/Block.h" #include "../voxels/voxel.h" #include "../voxels/Chunks.h" @@ -211,6 +212,7 @@ void PlayerController::updateCameraControl() { } void PlayerController::updateInteraction(){ + const ContentIndices* contentIds = level->contentIds; Chunks* chunks = level->chunks; Player* player = level->player; Lighting* lighting = level->lighting; @@ -241,7 +243,7 @@ void PlayerController::updateInteraction(){ int z = (int)iend.z; uint8_t states = 0; - if (Block::blocks[player->choosenBlock]->rotatable){ + if (contentIds->getBlockDef(player->choosenBlock)->rotatable){ if (abs(norm.x) > abs(norm.z)){ if (abs(norm.x) > abs(norm.y)) states = BLOCK_DIR_X; if (abs(norm.x) < abs(norm.y)) states = BLOCK_DIR_Y; @@ -252,7 +254,7 @@ void PlayerController::updateInteraction(){ } } - Block* block = Block::blocks[vox->id]; + Block* block = contentIds->getBlockDef(vox->id); if (lclick && block->breakable){ chunks->set(x,y,z, 0, 0); lighting->onBlockSet(x,y,z, 0); diff --git a/src/voxel_engine.cpp b/src/voxel_engine.cpp index 05d82244..509fff61 100644 --- a/src/voxel_engine.cpp +++ b/src/voxel_engine.cpp @@ -6,86 +6,19 @@ #include #include "definitions.h" - -#include "util/platform.h" #include "engine.h" - +#include "util/platform.h" #include "coders/toml.h" -#include "coders/json.h" #include "files/files.h" - -#include "window/Events.h" - -toml::Wrapper create_wrapper(EngineSettings& settings) { - toml::Wrapper wrapper; - toml::Section& display = wrapper.add("display"); - display.add("width", &settings.display.width); - display.add("height", &settings.display.height); - display.add("samples", &settings.display.samples); - display.add("swap-interval", &settings.display.swapInterval); - - toml::Section& chunks = wrapper.add("chunks"); - chunks.add("load-distance", &settings.chunks.loadDistance); - chunks.add("load-speed", &settings.chunks.loadSpeed); - chunks.add("padding", &settings.chunks.padding); - - toml::Section& camera = wrapper.add("camera"); - camera.add("fov-effects", &settings.camera.fovEvents); - camera.add("shaking", &settings.camera.shaking); - - toml::Section& graphics = wrapper.add("graphics"); - graphics.add("fog-curve", &settings.graphics.fogCurve); - - toml::Section& debug = wrapper.add("debug"); - debug.add("generator-test-mode", &settings.debug.generatorTestMode); - return wrapper; -} - -std::string write_controls() { - json::JObject* obj = new json::JObject(); - for (auto& entry : Events::bindings) { - const auto& binding = entry.second; - - json::JObject* jentry = new json::JObject(); - switch (binding.type) { - case inputtype::keyboard: jentry->put("type", "keyboard"); break; - case inputtype::mouse: jentry->put("type", "mouse"); break; - default: throw std::runtime_error("unsupported control type"); - } - jentry->put("code", binding.code); - obj->put(entry.first, jentry); - } - return json::stringify(obj, true, " "); -} - -void load_controls(std::string filename, std::string source) { - json::JObject* obj = json::parse(filename, source); - for (auto& entry : Events::bindings) { - auto& binding = entry.second; - - json::JObject* jentry = obj->obj(entry.first); - if (jentry == nullptr) - continue; - inputtype type; - std::string typestr; - jentry->str("type", typestr); - - if (typestr == "keyboard") { - type = inputtype::keyboard; - } else if (typestr == "mouse") { - type = inputtype::mouse; - } else { - std::cerr << "unknown input type '" << typestr << "'" << std::endl; - continue; - } - binding.type = type; - jentry->num("code", binding.code); - } -} +#include "files/settings_io.h" +#include "content/Content.h" int main() { platform::configure_encoding(); - setup_definitions(); + ContentBuilder contentBuilder; + setup_definitions(&contentBuilder); + + std::unique_ptr content(contentBuilder.build()); try { EngineSettings settings; toml::Wrapper wrapper = create_wrapper(settings); @@ -98,7 +31,7 @@ int main() { toml::Reader reader(&wrapper, settings_file.string(), content); reader.read(); } - Engine engine(settings); + Engine engine(settings, content.get()); setup_bindings(); if (std::filesystem::is_regular_file(controls_file)) { std::cout << "-- loading controls" << std::endl; diff --git a/src/voxels/Block.cpp b/src/voxels/Block.cpp index 49d399c5..880facf3 100644 --- a/src/voxels/Block.cpp +++ b/src/voxels/Block.cpp @@ -1,8 +1,6 @@ #include "Block.h" -Block* Block::blocks[256]; - -Block::Block(unsigned int id, int texture) : id(id), +Block::Block(std::string name, int texture) : name(name), textureFaces{texture,texture,texture,texture,texture,texture}, emission{0,0,0}{ } diff --git a/src/voxels/Block.h b/src/voxels/Block.h index d38fa2c4..bd177e74 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -1,6 +1,8 @@ #ifndef VOXELS_BLOCK_H_ #define VOXELS_BLOCK_H_ +#include + #define FACE_MX 0 #define FACE_PX 1 #define FACE_MY 2 @@ -14,9 +16,8 @@ enum class BlockModel { class Block { public: - static Block* blocks[256]; - - const unsigned int id; + std::string const name; + unsigned int id; // 0 1 2 3 4 5 int textureFaces[6]; // -x,x, -y,y, -z,z unsigned char emission[3]; @@ -30,7 +31,7 @@ public: bool rotatable = false; float hitboxScale = 1; - Block(unsigned int id, int texture); + Block(std::string name, int texture); }; #endif /* VOXELS_BLOCK_H_ */ diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 55eeef07..227faa25 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -3,6 +3,7 @@ #include "voxel.h" #include "Block.h" #include "WorldGenerator.h" +#include "../content/Content.h" #include "../lighting/Lightmap.h" #include "../files/WorldFiles.h" #include "../world/LevelEvents.h" @@ -16,8 +17,16 @@ using glm::vec3; using std::shared_ptr; -Chunks::Chunks(int w, int d, int ox, int oz, WorldFiles* wfile, LevelEvents* events) - : w(w), d(d), ox(ox), oz(oz), worldFiles(wfile), events(events) { +Chunks::Chunks(int w, int d, + int ox, int oz, + WorldFiles* wfile, + LevelEvents* events, + const Content* content) + : content(content), + contentIds(content->indices), + w(w), d(d), ox(ox), oz(oz), + worldFiles(wfile), + events(events) { volume = (size_t)w*(size_t)d; chunks = new shared_ptr[volume]; chunksSecond = new shared_ptr[volume]; @@ -59,7 +68,7 @@ bool Chunks::isObstacle(int x, int y, int z){ voxel* v = get(x,y,z); if (v == nullptr) return true; // void - is obstacle - return Block::blocks[v->id]->obstacle; + return contentIds->getBlockDef(v->id)->obstacle; } ubyte Chunks::getLight(int x, int y, int z, int channel){ @@ -191,7 +200,7 @@ voxel* Chunks::rayCast(vec3 start, while (t <= maxDist){ voxel* voxel = get(ix, iy, iz); - if (voxel == nullptr || Block::blocks[voxel->id]->selectable){ + if (voxel == nullptr || contentIds->getBlockDef(voxel->id)->selectable){ end.x = px + t * dx; end.y = py + t * dy; end.z = pz + t * dz; diff --git a/src/voxels/Chunks.h b/src/voxels/Chunks.h index b8ae4102..5f9ffa3d 100644 --- a/src/voxels/Chunks.h +++ b/src/voxels/Chunks.h @@ -8,6 +8,8 @@ class VoxelRenderer; +class Content; +class ContentIndices; class Chunk; class voxel; class WorldFiles; @@ -15,6 +17,8 @@ class LevelEvents; /* Player-centred chunks matrix */ class Chunks { + const Content* const content; + const ContentIndices* const contentIds; public: std::shared_ptr* chunks; std::shared_ptr* chunksSecond; @@ -27,7 +31,7 @@ public: LevelEvents* events; Chunks(int w, int d, int ox, int oz, - WorldFiles* worldFiles, LevelEvents* events); + WorldFiles* worldFiles, LevelEvents* events, const Content* content); ~Chunks(); bool putChunk(std::shared_ptr chunk); diff --git a/src/voxels/ChunksController.cpp b/src/voxels/ChunksController.cpp index 78ec6f16..2073b117 100644 --- a/src/voxels/ChunksController.cpp +++ b/src/voxels/ChunksController.cpp @@ -4,6 +4,7 @@ #include "Chunks.h" #include "ChunksStorage.h" #include "WorldGenerator.h" +#include "../content/Content.h" #include "../graphics/Mesh.h" #include "../lighting/Lighting.h" #include "../files/WorldFiles.h" @@ -26,10 +27,15 @@ using std::chrono::microseconds; ChunksController::ChunksController(Level* level, Chunks* chunks, Lighting* lighting, uint padding) - : level(level), chunks(chunks), lighting(lighting), padding(padding) { + : level(level), + chunks(chunks), + lighting(lighting), + padding(padding), + generator(new WorldGenerator(level->content)) { } ChunksController::~ChunksController(){ + delete generator; } void ChunksController::update(int64_t maxDuration) { @@ -50,6 +56,7 @@ 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; @@ -99,15 +106,16 @@ bool ChunksController::loadVisible(){ chunks->putChunk(chunk); if (!chunk->isLoaded()) { - WorldGenerator::generate(chunk->voxels, chunk->x, chunk->z, level->world->seed); + generator->generate(chunk->voxels, chunk->x, chunk->z, level->world->seed); chunk->setUnsaved(true); } chunk->updateHeights(); + ContentIndices* indices = content->indices; for (size_t i = 0; i < CHUNK_VOL; i++) { blockid_t id = chunk->voxels[i].id; - if (Block::blocks[id] == nullptr) { + 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; diff --git a/src/voxels/ChunksController.h b/src/voxels/ChunksController.h index 1a2b0908..7c6e37c1 100644 --- a/src/voxels/ChunksController.h +++ b/src/voxels/ChunksController.h @@ -9,6 +9,7 @@ class Lighting; class WorldFiles; class VoxelRenderer; class ChunksLoader; +class WorldGenerator; class ChunksController { private: @@ -17,6 +18,7 @@ private: Lighting* lighting; int64_t avgDurationMcs = 1000; uint padding; + WorldGenerator* generator; public: ChunksController(Level* level, Chunks* chunks, Lighting* lighting, uint padding); ~ChunksController(); diff --git a/src/voxels/WorldGenerator.cpp b/src/voxels/WorldGenerator.cpp index e6b0e088..8ba1b677 100644 --- a/src/voxels/WorldGenerator.cpp +++ b/src/voxels/WorldGenerator.cpp @@ -1,6 +1,7 @@ #include "WorldGenerator.h" #include "voxel.h" #include "Chunk.h" +#include "Block.h" #include #include @@ -11,8 +12,9 @@ #define FNL_IMPL #include "../maths/FastNoiseLite.h" -#include "../definitions.h" +#include "../content/Content.h" #include "../maths/voxmaths.h" +#include "../core_defs.h" #define SEA_LEVEL 55 @@ -94,6 +96,19 @@ float calc_height(fnl_state *noise, int real_x, int real_z){ return height; } +WorldGenerator::WorldGenerator(const Content* content) + : idStone(content->require("base:stone")->id), + idDirt(content->require("base:dirt")->id), + idGrassBlock(content->require("base:grass_block")->id), + idSand(content->require("base:sand")->id), + idWater(content->require("base:water")->id), + idWood(content->require("base:wood")->id), + idLeaves(content->require("base:leaves")->id), + idGrass(content->require("base:grass")->id), + idFlower(content->require("base:flower")->id), + idBedrock(content->require("base:bedrock")->id) {; +} + int generate_tree(fnl_state *noise, PseudoRandom* random, Map2D& heights, @@ -179,14 +194,14 @@ void WorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){ for (int y = 0; y < CHUNK_H; y++){ int real_y = y; - int id = real_y < SEA_LEVEL ? BLOCK_WATER : BLOCK_AIR; + int id = real_y < SEA_LEVEL ? idWater : BLOCK_AIR; int states = 0; if ((real_y == (int)height) && (SEA_LEVEL-2 < real_y)) { - id = BLOCK_GRASS_BLOCK; + id = idGrassBlock; } else if (real_y < (height - 6)){ - id = BLOCK_STONE; + id = idStone; } else if (real_y < height){ - id = BLOCK_DIRT; + id = idDirt; } else { int tree = generate_tree(&noise, &randomtree, heights, humidity, real_x, real_y, real_z, treesTile); if (tree) { @@ -195,20 +210,20 @@ void WorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){ } } if (((height - (1.5 - 0.2 * pow(height - 54, 4))) < real_y) && (real_y < height) && humidity.get(real_x, real_z) < 0.1){ - id = BLOCK_SAND; + id = idSand; } if (real_y <= 2) - id = BLOCK_BEDROCK; + id = idBedrock; randomgrass.setSeed(real_x,real_z); if ((id == 0) && (height > SEA_LEVEL+0.5) && ((int)(height + 1) == real_y) && ((unsigned short)randomgrass.rand() > 56000)){ - id = BLOCK_GRASS; + id = idGrass; } if ((id == 0) && (height > SEA_LEVEL+0.5) && ((int)(height + 1) == real_y) && ((unsigned short)randomgrass.rand() > 65000)){ - id = BLOCK_FLOWER; + id = idFlower; } if ((height > SEA_LEVEL+1) && ((int)(height + 1) == real_y) && ((unsigned short)randomgrass.rand() > 65533)){ - id = BLOCK_WOOD; + id = idWood; states = BLOCK_DIR_Y; } voxels[(y * CHUNK_D + z) * CHUNK_W + x].id = id; diff --git a/src/voxels/WorldGenerator.h b/src/voxels/WorldGenerator.h index 0b910441..f5aa82fa 100644 --- a/src/voxels/WorldGenerator.h +++ b/src/voxels/WorldGenerator.h @@ -1,11 +1,25 @@ #ifndef VOXELS_WORLDGENERATOR_H_ #define VOXELS_WORLDGENERATOR_H_ +#include "../typedefs.h" + class voxel; +class Content; class WorldGenerator { + blockid_t const idStone; + blockid_t const idDirt; + blockid_t const idGrassBlock; + blockid_t const idSand; + blockid_t const idWater; + blockid_t const idWood; + blockid_t const idLeaves; + blockid_t const idGrass; + blockid_t const idFlower; + blockid_t const idBedrock; public: - static void generate(voxel* voxels, int x, int z, int seed); + WorldGenerator(const Content* content); + void generate(voxel* voxels, int x, int z, int seed); }; #endif /* VOXELS_WORLDGENERATOR_H_ */ diff --git a/src/world/Level.cpp b/src/world/Level.cpp index 293eda3f..35743542 100644 --- a/src/world/Level.cpp +++ b/src/world/Level.cpp @@ -1,6 +1,7 @@ #include "Level.h" #include "World.h" #include "LevelEvents.h" +#include "../content/Content.h" #include "../lighting/Lighting.h" #include "../voxels/Chunk.h" #include "../voxels/Chunks.h" @@ -11,8 +12,10 @@ #include "../objects/Player.h" #include "../objects/player_control.h" -Level::Level(World* world, Player* player, EngineSettings& settings) +Level::Level(World* world, const Content* content, Player* player, EngineSettings& settings) : world(world), + content(content), + contentIds(content->indices), player(player), chunksStorage(new ChunksStorage(this)), events(new LevelEvents()) , @@ -24,8 +27,9 @@ Level::Level(World* world, Player* player, EngineSettings& settings) chunks = new Chunks(matrixSize, matrixSize, 0, 0, world->wfile, - events); - lighting = new Lighting(chunks); + events, + content); + lighting = new Lighting(content, chunks); chunksController = new ChunksController(this, chunks, lighting, settings.chunks.padding); playerController = new PlayerController(this, settings); diff --git a/src/world/Level.h b/src/world/Level.h index 1ba0b9d1..084b9cd3 100644 --- a/src/world/Level.h +++ b/src/world/Level.h @@ -4,6 +4,8 @@ #include "../typedefs.h" #include "../settings.h" +class Content; +class ContentIndices; class World; class Player; class Chunks; @@ -17,6 +19,8 @@ class PlayerController; class Level { public: World* world; + const Content* const content; + const ContentIndices* const contentIds; Player* player; Chunks* chunks; ChunksStorage* chunksStorage; @@ -28,6 +32,7 @@ public: const EngineSettings& settings; Level(World* world, + const Content* content, Player* player, EngineSettings& settings); ~Level(); diff --git a/src/world/World.cpp b/src/world/World.cpp index e240fd85..23db425d 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -42,7 +42,7 @@ void World::write(Level* level, bool writeChunks) { wfile->writePlayer(level->player); } -Level* World::load(EngineSettings& settings) { +Level* World::load(EngineSettings& settings, const Content* content) { WorldInfo info {name, wfile->directory, seed}; wfile->readWorldInfo(info); seed = info.seed; @@ -51,7 +51,7 @@ Level* World::load(EngineSettings& settings) { vec3 playerPosition = vec3(0, 100, 0); Camera* camera = new Camera(playerPosition, glm::radians(90.0f)); Player* player = new Player(playerPosition, 4.0f, camera); - Level* level = new Level(this, player, settings); + Level* level = new Level(this, content, player, settings); wfile->readPlayer(player); camera->rotation = mat4(1.0f); diff --git a/src/world/World.h b/src/world/World.h index c2d12694..d5d63f7c 100644 --- a/src/world/World.h +++ b/src/world/World.h @@ -6,6 +6,7 @@ #include "../typedefs.h" #include "../settings.h" +class Content; class WorldFiles; class Chunks; class Level; @@ -24,7 +25,7 @@ public: ~World(); void write(Level* level, bool writeChunks); - Level* load(EngineSettings& settings); + Level* load(EngineSettings& settings, const Content* content); }; #endif /* WORLD_WORLD_H_ */ \ No newline at end of file