Base content package + ContentLoader

This commit is contained in:
MihailRis 2023-12-01 16:26:42 +03:00
parent 6708e1ef86
commit c8a283c645
33 changed files with 318 additions and 112 deletions

View File

@ -0,0 +1,4 @@
{
"texture": "bazalt",
"breakable": false
}

View File

@ -0,0 +1,4 @@
{
"texture": "blue_lamp",
"emission": [0, 0, 15]
}

View File

@ -0,0 +1,3 @@
{
"texture": "brick"
}

View File

@ -0,0 +1,3 @@
{
"texture": "dirt"
}

View File

@ -0,0 +1,9 @@
{
"texture": "flower",
"draw-group": 1,
"light-passing": true,
"obstacle": false,
"replaceable": true,
"model": "X",
"hitbox": [0.15, 0.0, 0.15, 0.7, 0.7, 0.7]
}

View File

@ -0,0 +1,5 @@
{
"texture": "glass",
"draw-group": 2,
"light-passing": true
}

View File

@ -0,0 +1,9 @@
{
"texture": "grass",
"draw-group": 1,
"light-passing": true,
"obstacle": false,
"replaceable": true,
"model": "X",
"hitbox": [0.15, 0.0, 0.15, 0.7, 0.7, 0.7]
}

View File

@ -0,0 +1,10 @@
{
"texture-faces": [
"grass_side",
"grass_side",
"dirt",
"grass_top",
"grass_side",
"grass_side"
]
}

View File

@ -0,0 +1,4 @@
{
"texture": "green_lamp",
"emission": [0, 15, 0]
}

View File

@ -0,0 +1,4 @@
{
"texture": "lamp",
"emission": [15, 14, 13]
}

View File

@ -0,0 +1,3 @@
{
"texture": "leaves"
}

View File

@ -0,0 +1,3 @@
{
"texture": "metal"
}

View File

@ -0,0 +1,14 @@
{
"texture-faces": [
"pane_side",
"pane_side",
"pane_side_2",
"pane_side_2",
"pane",
"pane"
],
"model": "aabb",
"hitbox": [0.0, 0.0, 0.0, 1.0, 1.0, 0.1],
"light-passing": true,
"sky-light-passing": true
}

View File

@ -0,0 +1,3 @@
{
"texture": "planks"
}

View File

@ -0,0 +1,4 @@
{
"texture": "red_lamp",
"emission": [15, 0, 0]
}

View File

@ -0,0 +1,3 @@
{
"texture": "rust"
}

View File

@ -0,0 +1,3 @@
{
"texture": "sand"
}

View File

@ -0,0 +1,3 @@
{
"texture": "stone"
}

View File

@ -0,0 +1,9 @@
{
"texture": "water",
"draw-group": 3,
"light-passing": true,
"sky-light-passing": false,
"obstacle": false,
"selectable": false,
"replaceable": true
}

View File

@ -0,0 +1,11 @@
{
"texture-faces": [
"wood",
"wood",
"wood_top",
"wood_top",
"wood",
"wood"
],
"rotatable": true
}

View File

@ -0,0 +1,27 @@
{
"id": "base",
"version": "0.15",
"description": "basic content package",
"blocks": [
"dirt",
"grass_block",
"lamp",
"glass",
"planks",
"wood",
"leaves",
"stone",
"water",
"sand",
"bazalt",
"grass",
"flower",
"brick",
"metal",
"rust",
"red_lamp",
"green_lamp",
"blue_lamp",
"pane"
]
}

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -190,6 +190,12 @@ void JObject::num(std::string key, double& dst) const {
dst = found->second->value.num; dst = found->second->value.num;
} }
void JObject::num(std::string key, ubyte& dst) const {
auto found = map.find(key);
if (found != map.end())
dst = found->second->value.num;
}
void JObject::num(std::string key, float& dst) const { void JObject::num(std::string key, float& dst) const {
auto found = map.find(key); auto found = map.find(key);
if (found != map.end()) if (found != map.end())
@ -289,6 +295,10 @@ JObject& JObject::put(string key, bool value){
return *this; return *this;
} }
bool JObject::has(string key) {
return map.find(key) != map.end();
}
Value::Value(valtype type, valvalue value) : type(type), value(value) { Value::Value(valtype type, valvalue value) : type(type), value(value) {
} }

View File

@ -72,6 +72,7 @@ namespace json {
void num(std::string key, int& dst) const; void num(std::string key, int& dst) const;
void num(std::string key, float& dst) const; void num(std::string key, float& dst) const;
void num(std::string key, uint& dst) const; void num(std::string key, uint& dst) const;
void num(std::string key, ubyte& dst) const;
void num(std::string key, double& dst) const; void num(std::string key, double& dst) const;
JObject* obj(std::string key) const; JObject* obj(std::string key) const;
JArray* arr(std::string key) const; JArray* arr(std::string key) const;
@ -86,6 +87,8 @@ namespace json {
JObject& put(std::string key, JObject* value); JObject& put(std::string key, JObject* value);
JObject& put(std::string key, JArray* value); JObject& put(std::string key, JArray* value);
JObject& put(std::string key, bool value); JObject& put(std::string key, bool value);
bool has(std::string key);
}; };
class Parser : public BasicParser { class Parser : public BasicParser {

View File

@ -60,8 +60,8 @@ ContentIndices::ContentIndices(vector<Block*> blockDefs)
Content::Content(ContentIndices* indices, DrawGroups* drawGroups, Content::Content(ContentIndices* indices, DrawGroups* drawGroups,
unordered_map<string, Block*> blockDefs) unordered_map<string, Block*> blockDefs)
: blockDefs(blockDefs), : blockDefs(blockDefs),
drawGroups(drawGroups), indices(indices),
indices(indices) { drawGroups(drawGroups) {
} }
Content::~Content() { Content::~Content() {

View File

@ -0,0 +1,124 @@
#include "ContentLoader.h"
#include <iostream>
#include <string>
#include <memory>
#include "Content.h"
#include "../voxels/Block.h"
#include "../files/files.h"
#include "../coders/json.h"
#include "../typedefs.h"
#include <glm/glm.hpp>
using glm::vec3;
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::unique_ptr;
using std::filesystem::path;
ContentLoader::ContentLoader(path folder) : folder(folder) {}
// TODO: add basic validation and logging
Block* ContentLoader::loadBlock(string name, path file) {
string source = files::read_string(file);
unique_ptr<json::JObject> root = nullptr;
try {
root.reset(json::parse(file.string(), source));
} catch (const parsing_error& error) {
cerr << error.errorLog() << endl;
throw std::runtime_error("could not load block def");
}
unique_ptr<Block> def(new Block(name));
// block texturing
if (root->has("texture")) {
string texture;
root->str("texture", texture);
for (uint i = 0; i < 6; i++)
def->textureFaces[i] = texture;
} else if (root->has("texture-faces")) {
json::JArray* texarr = root->arr("texture-faces");
for (uint i = 0; i < 6; i++) {
def->textureFaces[i] = texarr->str(i);
}
}
// block model
string model = "block";
root->str("model", model);
if (model == "block") def->model = BlockModel::block;
else if (model == "aabb") def->model = BlockModel::aabb;
else if (model == "X") def->model = BlockModel::xsprite;
else if (model == "none") def->model = BlockModel::none;
else {
cerr << "unknown model " << model << endl;
def->model = BlockModel::none;
}
// block hitbox AABB [x, y, z, width, height, depth]
json::JArray* hitboxobj = root->arr("hitbox");
if (hitboxobj) {
AABB& aabb = def->hitbox;
aabb.a = vec3(hitboxobj->num(0), hitboxobj->num(1), hitboxobj->num(2));
aabb.b = vec3(hitboxobj->num(3), hitboxobj->num(4), hitboxobj->num(5));
aabb.b += aabb.a;
}
// block light emission [r, g, b] where r,g,b in range [0..15]
json::JArray* emissionobj = root->arr("emission");
if (emissionobj) {
def->emission[0] = emissionobj->num(0);
def->emission[1] = emissionobj->num(1);
def->emission[2] = emissionobj->num(2);
}
// primitive properties
root->flag("obstacle", def->obstacle);
root->flag("replaceable", def->replaceable);
root->flag("light-passing", def->lightPassing);
root->flag("breakable", def->breakable);
root->flag("selectable", def->selectable);
root->flag("rotatable", def->rotatable);
root->flag("sky-light-passing", def->skyLightPassing);
root->num("draw-group", def->drawGroup);
return def.release();
}
void ContentLoader::load(ContentBuilder* builder) {
cout << "-- loading content " << folder << endl;
path file = folder / path("package.json");
string source = files::read_string(file);
unique_ptr<json::JObject> root = nullptr;
try {
root.reset(json::parse(file.filename().string(), source));
} catch (const parsing_error& error) {
cerr << error.errorLog() << endl;
throw std::runtime_error("could not load content package");
}
string id;
string version;
root->str("id", id);
root->str("version", version);
cout << " id: " << id << endl;
cout << " version: " << version << endl;
json::JArray* blocksarr = root->arr("blocks");
if (blocksarr) {
cout << " blocks: " << blocksarr->size() << endl;
for (uint i = 0; i < blocksarr->size(); i++) {
string name = blocksarr->str(i);
cout << " loading block " << id << ":" << name << endl;
path blockfile = folder/path("blocks/"+name+".json");
builder->add(loadBlock(id+":"+name, blockfile));
}
}
}

View File

@ -0,0 +1,19 @@
#ifndef CONTENT_CONTENT_LOADER_H_
#define CONTENT_CONTENT_LOADER_H_
#include <string>
#include <filesystem>
class Block;
class ContentBuilder;
class ContentLoader {
std::filesystem::path folder;
public:
ContentLoader(std::filesystem::path folder);
Block* loadBlock(std::string name, std::filesystem::path file);
void load(ContentBuilder* builder);
};
#endif // CONTENT_CONTENT_LOADER_H_

View File

@ -21,107 +21,6 @@ void setup_definitions(ContentBuilder* builder) {
block->selectable = false; block->selectable = false;
block->model = BlockModel::none; block->model = BlockModel::none;
builder->add(block); builder->add(block);
block = new Block("base:dirt", "dirt");
builder->add(block);
block = new Block("base:grass_block", "grass_side");
block->textureFaces[2] = "dirt";
block->textureFaces[3] = "grass_top";
builder->add(block);
block = new Block("base:lamp", "lamp");
block->emission[0] = 15;
block->emission[1] = 14;
block->emission[2] = 13;
builder->add(block);
block = new Block("base:glass", "glass");
block->drawGroup = 2;
block->lightPassing = true;
builder->add(block);
block = new Block("base:planks", "planks");
builder->add(block);
block = new Block("base:wood", "wood");
block->textureFaces[2] = "wood_top";
block->textureFaces[3] = "wood_top";
block->rotatable = true;
builder->add(block);
block = new Block("base:leaves", "leaves");
builder->add(block);
block = new Block("base:stone", "stone");
builder->add(block);
block = new Block("base:water", "water");
block->drawGroup = 3;
block->lightPassing = true;
block->skyLightPassing = false;
block->obstacle = false;
block->selectable = false;
block->replaceable = true;
builder->add(block);
block = new Block("base:sand", "sand");
builder->add(block);
block = new Block("base:bedrock", "bedrock");
block->breakable = false;
builder->add(block);
block = new Block("base:grass", "grass");
block->drawGroup = 1;
block->lightPassing = true;
block->obstacle = false;
block->replaceable = true;
block->model = BlockModel::xsprite;
block->hitbox.scale(vec3(0.7f), vec3(0.5f, 0.0f, 0.5f));
builder->add(block);
block = new Block("base:flower", "flower");
block->drawGroup = 1;
block->lightPassing = true;
block->obstacle = false;
block->replaceable = true;
block->model = BlockModel::xsprite;
block->hitbox.scale(vec3(0.7f));
builder->add(block);
block = new Block("base:brick", "brick");
builder->add(block);
block = new Block("base:metal", "metal");
builder->add(block);
block = new Block("base:rust", "rust");
builder->add(block);
block = new Block("base:red_lamp", "red_lamp");
block->emission[0] = 15;
builder->add(block);
block = new Block("base:green_lamp", "green_lamp");
block->emission[1] = 15;
builder->add(block);
block = new Block("base:blue_lamp", "blue_lamp");
block->emission[2] = 15;
builder->add(block);
// block added for test
block = new Block("base:pane", "pane");
block->textureFaces[FACE_MX] = "pane_side";
block->textureFaces[FACE_PX] = "pane_side";
block->textureFaces[FACE_MY] = "pane_side_2";
block->textureFaces[FACE_PY] = "pane_side_2";
block->model = BlockModel::aabb;
block->hitbox.scale(vec3(1.0f, 1.0f, 0.2f), vec3(0.5f, 0.5f, 0.0f));
block->lightPassing = true;
block->skyLightPassing = true;
builder->add(block);
} }
void setup_bindings() { void setup_bindings() {

View File

@ -13,6 +13,7 @@
#include "files/settings_io.h" #include "files/settings_io.h"
#include "files/engine_paths.h" #include "files/engine_paths.h"
#include "content/Content.h" #include "content/Content.h"
#include "content/ContentLoader.h"
#include "coders/png.h" #include "coders/png.h"
#include "graphics/Atlas.h" #include "graphics/Atlas.h"
@ -20,6 +21,8 @@
#include "util/command_line.h" #include "util/command_line.h"
using std::filesystem::path;
int main(int argc, char** argv) { int main(int argc, char** argv) {
EnginePaths paths; EnginePaths paths;
if (!parse_cmdline(argc, argv, paths)) if (!parse_cmdline(argc, argv, paths))
@ -28,14 +31,17 @@ int main(int argc, char** argv) {
platform::configure_encoding(); platform::configure_encoding();
ContentBuilder contentBuilder; ContentBuilder contentBuilder;
setup_definitions(&contentBuilder); setup_definitions(&contentBuilder);
// TODO: implement worlds indexing
ContentLoader loader(paths.getResources()/path("content/base"));
loader.load(&contentBuilder);
std::unique_ptr<Content> content(contentBuilder.build()); std::unique_ptr<Content> content(contentBuilder.build());
try { try {
EngineSettings settings; EngineSettings settings;
toml::Wrapper wrapper = create_wrapper(settings); toml::Wrapper wrapper = create_wrapper(settings);
std::filesystem::path settings_file = platform::get_settings_file(); path settings_file = platform::get_settings_file();
std::filesystem::path controls_file = platform::get_controls_file(); path controls_file = platform::get_controls_file();
if (std::filesystem::is_regular_file(settings_file)) { if (std::filesystem::is_regular_file(settings_file)) {
std::cout << "-- loading settings" << std::endl; std::cout << "-- loading settings" << std::endl;
std::string content = files::read_string(settings_file); std::string content = files::read_string(settings_file);

View File

@ -1,6 +1,12 @@
#include "Block.h" #include "Block.h"
Block::Block(std::string name, std::string texture) : name(name), Block::Block(std::string name)
textureFaces{texture,texture,texture,texture,texture,texture}, : name(name),
emission{0,0,0}{ textureFaces({"notfound","notfound","notfound",
"notfound","notfound","notfound",}) {
}
Block::Block(std::string name, std::string texture) : name(name),
textureFaces{texture,texture,texture,texture,texture,texture} {
} }

View File

@ -27,7 +27,7 @@ public:
std::string const name; std::string const name;
// 0 1 2 3 4 5 // 0 1 2 3 4 5
std::string textureFaces[6]; // -x,x, -y,y, -z,z std::string textureFaces[6]; // -x,x, -y,y, -z,z
unsigned char emission[4]; unsigned char emission[4] {0, 0, 0, 0};
unsigned char drawGroup = 0; unsigned char drawGroup = 0;
BlockModel model = BlockModel::block; BlockModel model = BlockModel::block;
bool lightPassing = false; bool lightPassing = false;
@ -46,6 +46,7 @@ public:
bool hitboxGrid[BLOCK_AABB_GRID][BLOCK_AABB_GRID][BLOCK_AABB_GRID]; bool hitboxGrid[BLOCK_AABB_GRID][BLOCK_AABB_GRID][BLOCK_AABB_GRID];
} rt; } rt;
Block(std::string name);
Block(std::string name, std::string texture); Block(std::string name, std::string texture);
}; };

View File

@ -106,7 +106,7 @@ WorldGenerator::WorldGenerator(const Content* content)
idLeaves(content->require("base:leaves")->rt.id), idLeaves(content->require("base:leaves")->rt.id),
idGrass(content->require("base:grass")->rt.id), idGrass(content->require("base:grass")->rt.id),
idFlower(content->require("base:flower")->rt.id), idFlower(content->require("base:flower")->rt.id),
idBedrock(content->require("base:bedrock")->rt.id) {; idBazalt(content->require("base:bazalt")->rt.id) {;
} }
int generate_tree(fnl_state *noise, int generate_tree(fnl_state *noise,
@ -213,7 +213,7 @@ void WorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){
id = idSand; id = idSand;
} }
if (real_y <= 2) if (real_y <= 2)
id = idBedrock; id = idBazalt;
randomgrass.setSeed(real_x,real_z); randomgrass.setSeed(real_x,real_z);
if ((id == 0) && (height > SEA_LEVEL+0.5) && ((int)(height + 1) == real_y) && ((unsigned short)randomgrass.rand() > 56000)){ if ((id == 0) && (height > SEA_LEVEL+0.5) && ((int)(height + 1) == real_y) && ((unsigned short)randomgrass.rand() > 56000)){

View File

@ -16,7 +16,7 @@ class WorldGenerator {
blockid_t const idLeaves; blockid_t const idLeaves;
blockid_t const idGrass; blockid_t const idGrass;
blockid_t const idFlower; blockid_t const idFlower;
blockid_t const idBedrock; blockid_t const idBazalt;
public: public:
WorldGenerator(const Content* content); WorldGenerator(const Content* content);
void generate(voxel* voxels, int x, int z, int seed); void generate(voxel* voxels, int x, int z, int seed);