Introduced Content, ContentIndices, no more integer ids hardcoded, common refactor
This commit is contained in:
parent
f2f9343737
commit
3b03464d27
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
@ -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;
|
||||
}
|
||||
|
||||
|
||||
50
src/content/Content.cpp
Normal file
50
src/content/Content.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "Content.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#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<Block*> 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<Block*> blockDefs)
|
||||
: blockDefs(blockDefs) {
|
||||
}
|
||||
|
||||
Content::Content(ContentIndices* indices,
|
||||
unordered_map<string, Block*> 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;
|
||||
}
|
||||
57
src/content/Content.h
Normal file
57
src/content/Content.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef CONTENT_CONTENT_H_
|
||||
#define CONTENT_CONTENT_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include "../typedefs.h"
|
||||
|
||||
class Block;
|
||||
class Content;
|
||||
|
||||
class ContentBuilder {
|
||||
std::unordered_map<std::string, Block*> blockDefs;
|
||||
std::vector<std::string> 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<Block*> blockDefs;
|
||||
public:
|
||||
ContentIndices(std::vector<Block*> 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<std::string, Block*> blockDefs;
|
||||
public:
|
||||
ContentIndices* const indices;
|
||||
|
||||
Content(ContentIndices* indices,
|
||||
std::unordered_map<std::string, Block*> blockDefs);
|
||||
~Content();
|
||||
|
||||
Block* require(std::string id) const;
|
||||
};
|
||||
|
||||
#endif // CONTENT_CONTENT_H_
|
||||
@ -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() {
|
||||
|
||||
@ -4,25 +4,10 @@
|
||||
#include <iostream>
|
||||
#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
|
||||
|
||||
|
||||
@ -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> screen) {
|
||||
this->screen = screen;
|
||||
}
|
||||
|
||||
const Content* Engine::getContent() const {
|
||||
return content;
|
||||
}
|
||||
@ -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> 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> screen);
|
||||
|
||||
const Content* getContent() const;
|
||||
};
|
||||
|
||||
#endif // SRC_ENGINE_H_
|
||||
77
src/files/settings_io.cpp
Normal file
77
src/files/settings_io.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include "settings_io.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
12
src/files/settings_io.h
Normal file
12
src/files/settings_io.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef FILES_SETTINGS_IO_H_
|
||||
#define FILES_SETTINGS_IO_H_
|
||||
|
||||
#include <string>
|
||||
#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_
|
||||
@ -3,11 +3,13 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <assert.h>
|
||||
#include <stdexcept>
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#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<UINode>(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<UINode>(box));
|
||||
panel->add(shared_ptr<UINode>(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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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>(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>(screen));
|
||||
});
|
||||
panel->add(button);
|
||||
|
||||
@ -3,7 +3,9 @@
|
||||
#include <iostream>
|
||||
#include <GL/glew.h>
|
||||
#include <memory>
|
||||
#include <assert.h>
|
||||
|
||||
#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());
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -2,12 +2,14 @@
|
||||
#include <assert.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"
|
||||
|
||||
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);
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <queue>
|
||||
|
||||
class Chunks;
|
||||
class ContentIndices;
|
||||
|
||||
struct lightentry {
|
||||
int x;
|
||||
@ -15,10 +16,11 @@ struct lightentry {
|
||||
class LightSolver {
|
||||
std::queue<lightentry> addqueue;
|
||||
std::queue<lightentry> 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);
|
||||
|
||||
@ -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 <memory>
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -6,86 +6,19 @@
|
||||
#include <stdexcept>
|
||||
|
||||
#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> 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;
|
||||
|
||||
@ -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}{
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
#ifndef VOXELS_BLOCK_H_
|
||||
#define VOXELS_BLOCK_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#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_ */
|
||||
|
||||
@ -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<Chunk>[volume];
|
||||
chunksSecond = new shared_ptr<Chunk>[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;
|
||||
|
||||
@ -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<Chunk>* chunks;
|
||||
std::shared_ptr<Chunk>* 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> chunk);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "WorldGenerator.h"
|
||||
#include "voxel.h"
|
||||
#include "Chunk.h"
|
||||
#include "Block.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
@ -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;
|
||||
|
||||
@ -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_ */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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_ */
|
||||
Loading…
x
Reference in New Issue
Block a user