From 3b03464d27687e88a0e1af42ab14d09a4467da10 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 21 Nov 2023 11:38:59 +0300 Subject: [PATCH] Introduced Content, ContentIndices, no more integer ids hardcoded, common refactor --- res/textures/block.png | Bin 16371 -> 17272 bytes src/constants.h | 2 +- src/content/Content.cpp | 50 ++++++++++++ src/content/Content.h | 57 ++++++++++++++ src/definitions.cpp | 76 +++++++++--------- src/definitions.h | 19 +---- src/engine.cpp | 7 +- src/engine.h | 6 +- src/files/settings_io.cpp | 77 ++++++++++++++++++ src/files/settings_io.h | 12 +++ src/frontend/hud.cpp | 134 +++++++++++++------------------- src/frontend/hud.h | 2 +- src/frontend/menu.cpp | 5 +- src/frontend/world_render.cpp | 10 ++- src/graphics/BlocksRenderer.cpp | 15 +++- src/graphics/BlocksRenderer.h | 6 +- src/graphics/ChunksRenderer.cpp | 2 +- src/lighting/LightSolver.cpp | 7 +- src/lighting/LightSolver.h | 4 +- src/lighting/Lighting.cpp | 32 +++++--- src/lighting/Lighting.h | 14 ++-- src/objects/player_control.cpp | 6 +- src/voxel_engine.cpp | 83 ++------------------ src/voxels/Block.cpp | 4 +- src/voxels/Block.h | 9 ++- src/voxels/Chunks.cpp | 17 +++- src/voxels/Chunks.h | 6 +- src/voxels/ChunksController.cpp | 14 +++- src/voxels/ChunksController.h | 2 + src/voxels/WorldGenerator.cpp | 35 ++++++--- src/voxels/WorldGenerator.h | 16 +++- src/world/Level.cpp | 10 ++- src/world/Level.h | 5 ++ src/world/World.cpp | 4 +- src/world/World.h | 3 +- 35 files changed, 472 insertions(+), 279 deletions(-) create mode 100644 src/content/Content.cpp create mode 100644 src/content/Content.h create mode 100644 src/files/settings_io.cpp create mode 100644 src/files/settings_io.h diff --git a/res/textures/block.png b/res/textures/block.png index 8309b5457485627e3f5613dd68c01806e2ddab0c..2879bd8fc1951eb164d8ff9b9ade1dcee2554c00 100644 GIT binary patch delta 12352 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 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