refactor & add structures.json
This commit is contained in:
parent
519ebc05f1
commit
323c2f2935
@ -53,6 +53,11 @@ biomes = {
|
||||
{block="base:stone", height=-1},
|
||||
{block="base:bazalt", height=1},
|
||||
},
|
||||
structures = {
|
||||
"tree0",
|
||||
"tree1",
|
||||
"tree2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +65,7 @@ function load_structures()
|
||||
local structures = {}
|
||||
local names = {"tree0", "tree1", "tree2", "tower"}
|
||||
for i, name in ipairs(names) do
|
||||
local filename = "core:default.files/"..name
|
||||
local filename = "core:default/"..name
|
||||
debug.log("loading structure "..filename)
|
||||
table.insert(structures, generation.load_structure(filename))
|
||||
end
|
||||
|
||||
6
res/generators/default/structures.json
Normal file
6
res/generators/default/structures.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"tree0": {},
|
||||
"tree1": {},
|
||||
"tree2": {},
|
||||
"tower": {}
|
||||
}
|
||||
@ -10,6 +10,7 @@
|
||||
#include "objects/EntityDef.hpp"
|
||||
#include "objects/rigging.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
#include "world/generator/VoxelFragment.hpp"
|
||||
#include "world/generator/GeneratorDef.hpp"
|
||||
#include "ContentPack.hpp"
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "ContentPack.hpp"
|
||||
#include "items/ItemDef.hpp"
|
||||
#include "objects/EntityDef.hpp"
|
||||
#include "world/generator/VoxelFragment.hpp"
|
||||
#include "world/generator/GeneratorDef.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
|
||||
|
||||
@ -433,18 +433,6 @@ void ContentLoader::loadEntity(
|
||||
if (fs::exists(configFile)) loadEntity(def, full, configFile);
|
||||
}
|
||||
|
||||
|
||||
void ContentLoader::loadGenerator(
|
||||
GeneratorDef& def, const std::string& full, const std::string& name
|
||||
) {
|
||||
auto folder = pack->folder;
|
||||
auto generatorFile = folder / fs::path("generators/" + name + ".lua");
|
||||
if (!fs::exists(generatorFile)) {
|
||||
return;
|
||||
}
|
||||
def.script = scripting::load_generator(generatorFile);
|
||||
}
|
||||
|
||||
void ContentLoader::loadBlock(
|
||||
Block& def, const std::string& full, const std::string& name
|
||||
) {
|
||||
@ -523,6 +511,9 @@ void ContentLoader::load() {
|
||||
if (fs::is_directory(generatorsDir)) {
|
||||
for (const auto& entry : fs::directory_iterator(generatorsDir)) {
|
||||
const auto& file = entry.path();
|
||||
if (fs::is_directory(file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string name = file.stem().u8string();
|
||||
auto [packid, full, filename] =
|
||||
|
||||
74
src/content/loading/GeneratorLoader.cpp
Normal file
74
src/content/loading/GeneratorLoader.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include "../ContentLoader.hpp"
|
||||
|
||||
#include "../ContentPack.hpp"
|
||||
|
||||
#include "files/files.hpp"
|
||||
#include "logic/scripting/scripting.hpp"
|
||||
#include "world/generator/GeneratorDef.hpp"
|
||||
#include "world/generator/VoxelFragment.hpp"
|
||||
#include "debug/Logger.hpp"
|
||||
|
||||
static debug::Logger logger("generator-loader");
|
||||
|
||||
static VoxelStructureMeta load_structure_meta(
|
||||
const std::string& name, const dv::value& config
|
||||
) {
|
||||
VoxelStructureMeta meta;
|
||||
meta.name = name;
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
static std::vector<std::unique_ptr<GeneratingVoxelStructure>> load_structures(
|
||||
const fs::path& structuresFile
|
||||
) {
|
||||
auto structuresDir = structuresFile.parent_path();
|
||||
auto map = files::read_json(structuresFile);
|
||||
|
||||
std::vector<std::unique_ptr<GeneratingVoxelStructure>> structures;
|
||||
for (auto& [name, config] : map.asObject()) {
|
||||
auto structFile = structuresDir / fs::u8path(name + ".vox");
|
||||
logger.debug() << "loading voxel fragment " << structFile.u8string();
|
||||
if (!fs::exists(structFile)) {
|
||||
throw std::runtime_error("structure file does not exist (" +
|
||||
structFile.u8string());
|
||||
}
|
||||
auto fragment = std::make_unique<VoxelFragment>();
|
||||
fragment->deserialize(files::read_binary_json(structFile));
|
||||
|
||||
structures.push_back(std::make_unique<GeneratingVoxelStructure>(
|
||||
load_structure_meta(name, config),
|
||||
std::move(fragment)
|
||||
));
|
||||
}
|
||||
return structures;
|
||||
}
|
||||
|
||||
static void load_structures(GeneratorDef& def, const fs::path& structuresFile) {
|
||||
def.structures = load_structures(structuresFile);
|
||||
// build indices map
|
||||
for (size_t i = 0; i < def.structures.size(); i++) {
|
||||
auto& structure = def.structures[i];
|
||||
def.structuresIndices[structure->meta.name] = i;
|
||||
}
|
||||
}
|
||||
|
||||
static inline const auto STRUCTURES_FILE = fs::u8path("structures.json");
|
||||
static inline const auto GENERATORS_DIR = fs::u8path("generators");
|
||||
|
||||
void ContentLoader::loadGenerator(
|
||||
GeneratorDef& def, const std::string& full, const std::string& name
|
||||
) {
|
||||
auto packDir = pack->folder;
|
||||
auto generatorsDir = packDir / GENERATORS_DIR;
|
||||
auto folder = generatorsDir / fs::u8path(name);
|
||||
auto generatorFile = generatorsDir / fs::u8path(name + ".lua");
|
||||
if (!fs::exists(generatorFile)) {
|
||||
return;
|
||||
}
|
||||
auto structuresFile = folder / STRUCTURES_FILE;
|
||||
if (fs::exists(structuresFile)) {
|
||||
load_structures(def, structuresFile);
|
||||
}
|
||||
def.script = scripting::load_generator(generatorFile);
|
||||
}
|
||||
@ -4,7 +4,7 @@
|
||||
#include "files/util.hpp"
|
||||
#include "coders/binary_json.hpp"
|
||||
#include "world/Level.hpp"
|
||||
#include "world/generator/VoxelStructure.hpp"
|
||||
#include "world/generator/VoxelFragment.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "lua_custom_types.hpp"
|
||||
|
||||
@ -19,7 +19,7 @@ static int l_save_structure(lua::State* L) {
|
||||
}
|
||||
bool saveEntities = lua::toboolean(L, 4);
|
||||
|
||||
auto structure = VoxelStructure::create(level, pointA, pointB, saveEntities);
|
||||
auto structure = VoxelFragment::create(level, pointA, pointB, saveEntities);
|
||||
auto map = structure->serialize();
|
||||
|
||||
auto bytes = json::to_binary(map);
|
||||
@ -37,7 +37,7 @@ static int l_load_structure(lua::State* L) {
|
||||
}
|
||||
auto map = files::read_binary_json(path);
|
||||
|
||||
auto structure = std::make_shared<VoxelStructure>();
|
||||
auto structure = std::make_shared<VoxelFragment>();
|
||||
structure->deserialize(map);
|
||||
return lua::newuserdata<lua::LuaVoxelStructure>(L, std::move(structure));
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
struct fnl_state;
|
||||
class Heightmap;
|
||||
class VoxelStructure;
|
||||
class VoxelFragment;
|
||||
|
||||
namespace lua {
|
||||
class Userdata {
|
||||
@ -72,13 +72,13 @@ namespace lua {
|
||||
static_assert(!std::is_abstract<LuaHeightmap>());
|
||||
|
||||
class LuaVoxelStructure : public Userdata {
|
||||
std::shared_ptr<VoxelStructure> structure;
|
||||
std::shared_ptr<VoxelFragment> structure;
|
||||
public:
|
||||
LuaVoxelStructure(std::shared_ptr<VoxelStructure> structure);
|
||||
LuaVoxelStructure(std::shared_ptr<VoxelFragment> structure);
|
||||
|
||||
virtual ~LuaVoxelStructure();
|
||||
|
||||
std::shared_ptr<VoxelStructure> getStructure() const {
|
||||
std::shared_ptr<VoxelFragment> getStructure() const {
|
||||
return structure;
|
||||
}
|
||||
|
||||
|
||||
@ -2,12 +2,12 @@
|
||||
|
||||
#include "../lua_util.hpp"
|
||||
|
||||
#include "world/generator/VoxelStructure.hpp"
|
||||
#include "world/generator/VoxelFragment.hpp"
|
||||
#include "util/stringutil.hpp"
|
||||
|
||||
using namespace lua;
|
||||
|
||||
LuaVoxelStructure::LuaVoxelStructure(std::shared_ptr<VoxelStructure> structure)
|
||||
LuaVoxelStructure::LuaVoxelStructure(std::shared_ptr<VoxelFragment> structure)
|
||||
: structure(std::move(structure)) {}
|
||||
|
||||
LuaVoxelStructure::~LuaVoxelStructure() {
|
||||
|
||||
@ -32,8 +32,8 @@ public:
|
||||
seaLevel(seaLevel)
|
||||
{}
|
||||
|
||||
std::vector<std::shared_ptr<VoxelStructure>> loadStructures() override {
|
||||
std::vector<std::shared_ptr<VoxelStructure>> structures;
|
||||
std::vector<std::shared_ptr<VoxelFragment>> loadStructures() override {
|
||||
std::vector<std::shared_ptr<VoxelFragment>> structures;
|
||||
|
||||
auto L = lua::get_main_thread();
|
||||
lua::pushenv(L, *env);
|
||||
|
||||
11
src/world/generator/GeneratorDef.cpp
Normal file
11
src/world/generator/GeneratorDef.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "GeneratorDef.hpp"
|
||||
|
||||
#include "VoxelFragment.hpp"
|
||||
|
||||
GeneratingVoxelStructure::GeneratingVoxelStructure(
|
||||
VoxelStructureMeta meta,
|
||||
std::unique_ptr<VoxelFragment> structure
|
||||
) : structure(std::move(structure)), meta(std::move(meta)) {}
|
||||
|
||||
|
||||
GeneratorDef::GeneratorDef(std::string name) : name(std::move(name)) {}
|
||||
@ -1,14 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "maths/Heightmap.hpp"
|
||||
#include "StructurePlacement.hpp"
|
||||
|
||||
class Content;
|
||||
class VoxelStructure;
|
||||
class VoxelFragment;
|
||||
|
||||
struct VoxelStructureMeta {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct BlocksLayer {
|
||||
/// @brief Layer block
|
||||
@ -102,7 +108,7 @@ public:
|
||||
virtual ~GeneratorScript() = default;
|
||||
|
||||
/// @brief Load all structures
|
||||
virtual std::vector<std::shared_ptr<VoxelStructure>> loadStructures() = 0;
|
||||
virtual std::vector<std::shared_ptr<VoxelFragment>> loadStructures() = 0;
|
||||
|
||||
/// @brief Generates a heightmap with values in range 0..1
|
||||
/// @param offset position of the heightmap in the world
|
||||
@ -133,12 +139,25 @@ public:
|
||||
virtual void prepare(const Content* content) = 0;
|
||||
};
|
||||
|
||||
struct GeneratingVoxelStructure {
|
||||
VoxelStructureMeta meta;
|
||||
std::unique_ptr<VoxelFragment> structure;
|
||||
|
||||
GeneratingVoxelStructure(
|
||||
VoxelStructureMeta meta,
|
||||
std::unique_ptr<VoxelFragment> structure
|
||||
);
|
||||
};
|
||||
|
||||
/// @brief Generator information
|
||||
struct GeneratorDef {
|
||||
/// @brief Generator full name - packid:name
|
||||
std::string name;
|
||||
std::unique_ptr<GeneratorScript> script;
|
||||
|
||||
GeneratorDef(std::string name) : name(std::move(name)) {}
|
||||
std::unordered_map<std::string, size_t> structuresIndices;
|
||||
std::vector<std::unique_ptr<GeneratingVoxelStructure>> structures;
|
||||
|
||||
GeneratorDef(std::string name);
|
||||
GeneratorDef(const GeneratorDef&) = delete;
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include "VoxelStructure.hpp"
|
||||
#include "VoxelFragment.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <cstring>
|
||||
@ -10,7 +10,7 @@
|
||||
#include "voxels/VoxelsVolume.hpp"
|
||||
#include "world/Level.hpp"
|
||||
|
||||
std::unique_ptr<VoxelStructure> VoxelStructure::create(
|
||||
std::unique_ptr<VoxelFragment> VoxelFragment::create(
|
||||
Level* level, const glm::ivec3& a, const glm::ivec3& b, bool entities
|
||||
) {
|
||||
auto start = glm::min(a, b);
|
||||
@ -43,11 +43,11 @@ std::unique_ptr<VoxelStructure> VoxelStructure::create(
|
||||
voxels[i].state = volVoxels[i].state;
|
||||
}
|
||||
|
||||
return std::make_unique<VoxelStructure>(
|
||||
return std::make_unique<VoxelFragment>(
|
||||
size, std::move(voxels), std::move(blockNames));
|
||||
}
|
||||
|
||||
dv::value VoxelStructure::serialize() const {
|
||||
dv::value VoxelFragment::serialize() const {
|
||||
auto root = dv::object();
|
||||
root["version"] = STRUCTURE_FORMAT_VERSION;
|
||||
root["size"] = dv::to_value(size);
|
||||
@ -64,7 +64,7 @@ dv::value VoxelStructure::serialize() const {
|
||||
return root;
|
||||
}
|
||||
|
||||
void VoxelStructure::deserialize(const dv::value& src) {
|
||||
void VoxelFragment::deserialize(const dv::value& src) {
|
||||
size = glm::ivec3();
|
||||
dv::get_vec(src, "size", size);
|
||||
|
||||
@ -83,7 +83,7 @@ void VoxelStructure::deserialize(const dv::value& src) {
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelStructure::prepare(const Content& content) {
|
||||
void VoxelFragment::prepare(const Content& content) {
|
||||
auto volume = size.x*size.y*size.z;
|
||||
voxelsRuntime.resize(volume);
|
||||
for (size_t i = 0; i < volume; i++) {
|
||||
@ -93,7 +93,7 @@ void VoxelStructure::prepare(const Content& content) {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<VoxelStructure> VoxelStructure::rotated(const Content& content) const {
|
||||
std::unique_ptr<VoxelFragment> VoxelFragment::rotated(const Content& content) const {
|
||||
std::vector<voxel> newVoxels(voxels.size());
|
||||
|
||||
for (int y = 0; y < size.y; y++) {
|
||||
@ -115,7 +115,7 @@ std::unique_ptr<VoxelStructure> VoxelStructure::rotated(const Content& content)
|
||||
}
|
||||
}
|
||||
}
|
||||
auto newStructure = std::make_unique<VoxelStructure>(
|
||||
auto newStructure = std::make_unique<VoxelFragment>(
|
||||
// swap X and Z on 90 deg. rotation
|
||||
glm::ivec3(size.z, size.y, size.x),
|
||||
std::move(newVoxels),
|
||||
@ -11,7 +11,7 @@ inline constexpr int STRUCTURE_FORMAT_VERSION = 1;
|
||||
class Level;
|
||||
class Content;
|
||||
|
||||
class VoxelStructure : public Serializable {
|
||||
class VoxelFragment : public Serializable {
|
||||
glm::ivec3 size;
|
||||
|
||||
/// @brief Structure voxels indexed different to world content
|
||||
@ -22,9 +22,9 @@ class VoxelStructure : public Serializable {
|
||||
/// @brief Structure voxels built on prepare(...) call
|
||||
std::vector<voxel> voxelsRuntime;
|
||||
public:
|
||||
VoxelStructure() : size() {}
|
||||
VoxelFragment() : size() {}
|
||||
|
||||
VoxelStructure(
|
||||
VoxelFragment(
|
||||
glm::ivec3 size,
|
||||
std::vector<voxel> voxels,
|
||||
std::vector<std::string> blockNames
|
||||
@ -41,9 +41,9 @@ public:
|
||||
void prepare(const Content& content);
|
||||
|
||||
/// @brief Create structure copy rotated 90 deg. clockwise
|
||||
std::unique_ptr<VoxelStructure> rotated(const Content& content) const;
|
||||
std::unique_ptr<VoxelFragment> rotated(const Content& content) const;
|
||||
|
||||
static std::unique_ptr<VoxelStructure> create(
|
||||
static std::unique_ptr<VoxelFragment> create(
|
||||
Level* level, const glm::ivec3& a, const glm::ivec3& b, bool entities);
|
||||
|
||||
const glm::ivec3& getSize() const {
|
||||
@ -7,7 +7,7 @@
|
||||
#include "voxels/Block.hpp"
|
||||
#include "voxels/Chunk.hpp"
|
||||
#include "GeneratorDef.hpp"
|
||||
#include "VoxelStructure.hpp"
|
||||
#include "VoxelFragment.hpp"
|
||||
#include "util/timeutil.hpp"
|
||||
#include "util/listutil.hpp"
|
||||
#include "debug/Logger.hpp"
|
||||
@ -259,6 +259,8 @@ void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: put automatic placement here
|
||||
|
||||
for (const auto& placement : prototype.structures) {
|
||||
if (placement.structure < 0 || placement.structure >= structures.size()) {
|
||||
|
||||
@ -16,7 +16,7 @@ class Content;
|
||||
struct GeneratorDef;
|
||||
class Heightmap;
|
||||
struct Biome;
|
||||
class VoxelStructure;
|
||||
class VoxelFragment;
|
||||
|
||||
enum class ChunkPrototypeLevel {
|
||||
VOID=0, BIOMES, HEIGHTMAP, STRUCTURES
|
||||
@ -47,7 +47,7 @@ class WorldGenerator {
|
||||
/// @brief Chunk prototypes loading surround map
|
||||
SurroundMap surroundMap;
|
||||
|
||||
std::vector<std::array<std::shared_ptr<VoxelStructure>, 4>> structures;
|
||||
std::vector<std::array<std::shared_ptr<VoxelFragment>, 4>> structures;
|
||||
|
||||
/// @brief Generate chunk prototype (see ChunkPrototype)
|
||||
/// @param x chunk position X divided by CHUNK_W
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user