Files
VoxelEngine/src/content/ContentLoader.cpp
T

176 lines
5.8 KiB
C++

#include "ContentLoader.h"
#include <iostream>
#include <string>
#include <memory>
#include <algorithm>
#include <glm/glm.hpp>
#include "Content.h"
#include "../util/listutil.h"
#include "../voxels/Block.h"
#include "../files/files.h"
#include "../coders/json.h"
#include "../typedefs.h"
#include "ContentPack.h"
#include "../logic/scripting/scripting.h"
namespace fs = std::filesystem;
ContentLoader::ContentLoader(ContentPack* pack) : pack(pack) {
}
void ContentLoader::fixPackIndices() {
auto folder = pack->folder;
auto indexFile = pack->getContentFile();
auto blocksFolder = folder/ContentPack::BLOCKS_FOLDER;
std::unique_ptr<json::JObject> root;
if (fs::is_regular_file(indexFile)) {
root.reset(files::read_json(indexFile));
} else {
root.reset(new json::JObject());
}
std::vector<std::string> detectedBlocks;
std::vector<std::string> indexedBlocks;
if (fs::is_directory(blocksFolder)) {
for (auto entry : fs::directory_iterator(blocksFolder)) {
fs::path file = entry.path();
if (fs::is_regular_file(file) && file.extension() == ".json") {
std::string name = file.stem();
if (name[0] == '_')
continue;
detectedBlocks.push_back(name);
}
}
}
bool modified = false;
if (!root->has("blocks")) {
root->putArray("blocks");
}
json::JArray* blocksarr = root->arr("blocks");
if (blocksarr) {
for (uint i = 0; i < blocksarr->size(); i++) {
std::string name = blocksarr->str(i);
if (!util::contains(detectedBlocks, name)) {
blocksarr->remove(i);
i--;
modified = true;
continue;
}
indexedBlocks.push_back(name);
}
}
for (auto name : detectedBlocks) {
if (!util::contains(indexedBlocks, name)) {
blocksarr->put(name);
modified = true;
}
}
if (modified){
// rewrite modified json
std::cout << indexFile << std::endl;
files::write_string(indexFile, json::stringify(root.get(), true, " "));
}
}
// TODO: add basic validation and logging
Block* ContentLoader::loadBlock(std::string name, fs::path file) {
std::unique_ptr<json::JObject> root(files::read_json(file));
std::unique_ptr<Block> def(new Block(name));
// block texturing
if (root->has("texture")) {
std::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
std::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 {
std::cerr << "unknown model " << model << std::endl;
def->model = BlockModel::none;
}
// rotation profile
std::string profile = "none";
root->str("rotation", profile);
def->rotatable = profile != "none";
if (profile == "pipe") {
def->rotations = BlockRotProfile::PIPE;
} else if (profile == "pane") {
def->rotations = BlockRotProfile::PANE;
} else if (profile != "none") {
std::cerr << "unknown rotation profile " << profile << std::endl;
def->rotatable = false;
}
// block hitbox AABB [x, y, z, width, height, depth]
json::JArray* boxobj = root->arr("hitbox");
if (boxobj) {
AABB& aabb = def->hitbox;
aabb.a = glm::vec3(boxobj->num(0), boxobj->num(1), boxobj->num(2));
aabb.b = glm::vec3(boxobj->num(3), boxobj->num(4), boxobj->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("grounded", def->grounded);
root->flag("hidden", def->hidden);
root->flag("sky-light-passing", def->skyLightPassing);
root->num("draw-group", def->drawGroup);
return def.release();
}
void ContentLoader::load(ContentBuilder* builder) {
std::cout << "-- loading pack [" << pack->id << "]" << std::endl;
fixPackIndices();
auto folder = pack->folder;
std::unique_ptr<json::JObject> root (files::read_json(pack->getContentFile()));
json::JArray* blocksarr = root->arr("blocks");
if (blocksarr) {
for (uint i = 0; i < blocksarr->size(); i++) {
std::string name = blocksarr->str(i);
std::string prefix = pack->id+":"+name;
fs::path blockfile = folder/fs::path("blocks/"+name+".json");
Block* block = loadBlock(prefix, blockfile);
builder->add(block);
fs::path scriptfile = folder/fs::path("scripts/"+name+".lua");
if (fs::is_regular_file(scriptfile)) {
scripting::load_block_script(prefix, scriptfile, &block->rt.funcsset);
}
}
}
}