add generator definition file (.toml)
This commit is contained in:
parent
d839da7dab
commit
3d478aef08
4
res/content/base/generators/demo.toml
Normal file
4
res/content/base/generators/demo.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# 1 - temperature
|
||||||
|
# 2 - humidity
|
||||||
|
biome_parameters = 2
|
||||||
|
sea_level = 64
|
||||||
@ -1,9 +1,3 @@
|
|||||||
sea_level = 64
|
|
||||||
|
|
||||||
-- 1 - temperature
|
|
||||||
-- 2 - humidity
|
|
||||||
biome_parameters = 2
|
|
||||||
|
|
||||||
biomes = json.parse(file.read("base:generators/demo/biomes.json"))
|
biomes = json.parse(file.read("base:generators/demo/biomes.json"))
|
||||||
|
|
||||||
function place_structures(x, z, w, d, seed, hmap)
|
function place_structures(x, z, w, d, seed, hmap)
|
||||||
1
res/generators/default.toml
Normal file
1
res/generators/default.toml
Normal file
@ -0,0 +1 @@
|
|||||||
|
biome_parameters = 0
|
||||||
@ -1,5 +1,3 @@
|
|||||||
biome_parameters = 0
|
|
||||||
|
|
||||||
biomes = {flat = {
|
biomes = {flat = {
|
||||||
parameters = {},
|
parameters = {},
|
||||||
layers = {
|
layers = {
|
||||||
@ -9,7 +7,3 @@ biomes = {flat = {
|
|||||||
{height=-1, block="core:obstacle"}
|
{height=-1, block="core:obstacle"}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
function generate_heightmap(x, y, w, h, seed)
|
|
||||||
return Heightmap(w, h)
|
|
||||||
end
|
|
||||||
@ -49,7 +49,7 @@ static void detect_defs(
|
|||||||
if (name[0] == '_') {
|
if (name[0] == '_') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fs::is_regular_file(file) && file.extension() == ".json") {
|
if (fs::is_regular_file(file) && files::is_data_file(file)) {
|
||||||
detected.push_back(prefix.empty() ? name : prefix + ":" + name);
|
detected.push_back(prefix.empty() ? name : prefix + ":" + name);
|
||||||
} else if (fs::is_directory(file)) {
|
} else if (fs::is_directory(file)) {
|
||||||
detect_defs(file, name, detected);
|
detect_defs(file, name, detected);
|
||||||
|
|||||||
@ -66,14 +66,20 @@ void ContentLoader::loadGenerator(
|
|||||||
) {
|
) {
|
||||||
auto packDir = pack->folder;
|
auto packDir = pack->folder;
|
||||||
auto generatorsDir = packDir / GENERATORS_DIR;
|
auto generatorsDir = packDir / GENERATORS_DIR;
|
||||||
auto folder = generatorsDir / fs::u8path(name);
|
auto generatorFile = generatorsDir / fs::u8path(name + ".toml");
|
||||||
auto generatorFile = generatorsDir / fs::u8path(name + ".lua");
|
|
||||||
if (!fs::exists(generatorFile)) {
|
if (!fs::exists(generatorFile)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto map = files::read_toml(generatorsDir / fs::u8path(name + ".toml"));
|
||||||
|
map.at("biome_parameters").get(def.biomeParameters);
|
||||||
|
map.at("sea_level").get(def.seaLevel);
|
||||||
|
|
||||||
|
auto folder = generatorsDir / fs::u8path(name);
|
||||||
|
auto scriptFile = folder / fs::u8path("script.lua");
|
||||||
|
|
||||||
auto structuresFile = folder / STRUCTURES_FILE;
|
auto structuresFile = folder / STRUCTURES_FILE;
|
||||||
if (fs::exists(structuresFile)) {
|
if (fs::exists(structuresFile)) {
|
||||||
load_structures(def, structuresFile);
|
load_structures(def, structuresFile);
|
||||||
}
|
}
|
||||||
def.script = scripting::load_generator(generatorFile);
|
def.script = scripting::load_generator(def, scriptFile);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -159,3 +159,36 @@ std::vector<std::string> files::read_list(const fs::path& filename) {
|
|||||||
}
|
}
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "coders/json.hpp"
|
||||||
|
#include "coders/toml.hpp"
|
||||||
|
|
||||||
|
using DecodeFunc = dv::value(*)(std::string_view, std::string_view);
|
||||||
|
|
||||||
|
static std::map<fs::path, DecodeFunc> data_decoders {
|
||||||
|
{fs::u8path(".json"), json::parse},
|
||||||
|
{fs::u8path(".toml"), toml::parse},
|
||||||
|
};
|
||||||
|
|
||||||
|
bool files::is_data_file(const fs::path& file) {
|
||||||
|
return is_data_interchange_format(file.extension());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool files::is_data_interchange_format(const fs::path& ext) {
|
||||||
|
return data_decoders.find(ext) != data_decoders.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
dv::value files::read_object(const fs::path& file) {
|
||||||
|
const auto& found = data_decoders.find(file.extension());
|
||||||
|
if (found == data_decoders.end()) {
|
||||||
|
throw std::runtime_error("unknown file format");
|
||||||
|
}
|
||||||
|
auto text = read_string(file);
|
||||||
|
try {
|
||||||
|
return found->second(file.u8string(), text);
|
||||||
|
} catch (const parsing_error& err) {
|
||||||
|
throw std::runtime_error(err.errorLog());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -66,4 +66,8 @@ namespace files {
|
|||||||
dv::value read_binary_json(const fs::path& file);
|
dv::value read_binary_json(const fs::path& file);
|
||||||
dv::value read_toml(const fs::path& file);
|
dv::value read_toml(const fs::path& file);
|
||||||
std::vector<std::string> read_list(const fs::path& file);
|
std::vector<std::string> read_list(const fs::path& file);
|
||||||
|
|
||||||
|
bool is_data_file(const fs::path& file);
|
||||||
|
bool is_data_interchange_format(const fs::path& ext);
|
||||||
|
dv::value read_object(const fs::path& file);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,7 @@ class LevelController;
|
|||||||
class Entity;
|
class Entity;
|
||||||
struct EntityDef;
|
struct EntityDef;
|
||||||
class GeneratorScript;
|
class GeneratorScript;
|
||||||
|
struct GeneratorDef;
|
||||||
|
|
||||||
namespace scripting {
|
namespace scripting {
|
||||||
extern Engine* engine;
|
extern Engine* engine;
|
||||||
@ -147,6 +148,7 @@ namespace scripting {
|
|||||||
void load_entity_component(const std::string& name, const fs::path& file);
|
void load_entity_component(const std::string& name, const fs::path& file);
|
||||||
|
|
||||||
std::unique_ptr<GeneratorScript> load_generator(
|
std::unique_ptr<GeneratorScript> load_generator(
|
||||||
|
const GeneratorDef& def,
|
||||||
const fs::path& file
|
const fs::path& file
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -16,20 +16,17 @@
|
|||||||
#include "util/timeutil.hpp"
|
#include "util/timeutil.hpp"
|
||||||
|
|
||||||
class LuaGeneratorScript : public GeneratorScript {
|
class LuaGeneratorScript : public GeneratorScript {
|
||||||
|
const GeneratorDef& def;
|
||||||
scriptenv env;
|
scriptenv env;
|
||||||
std::vector<Biome> biomes;
|
std::vector<Biome> biomes;
|
||||||
uint biomeParameters;
|
|
||||||
uint seaLevel;
|
|
||||||
public:
|
public:
|
||||||
LuaGeneratorScript(
|
LuaGeneratorScript(
|
||||||
scriptenv env,
|
const GeneratorDef& def,
|
||||||
std::vector<Biome> biomes,
|
scriptenv env,
|
||||||
uint biomeParameters,
|
std::vector<Biome> biomes)
|
||||||
uint seaLevel)
|
: def(def),
|
||||||
: env(std::move(env)),
|
env(std::move(env)),
|
||||||
biomes(std::move(biomes)),
|
biomes(std::move(biomes))
|
||||||
biomeParameters(biomeParameters),
|
|
||||||
seaLevel(seaLevel)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::shared_ptr<Heightmap> generateHeightmap(
|
std::shared_ptr<Heightmap> generateHeightmap(
|
||||||
@ -56,6 +53,7 @@ public:
|
|||||||
) override {
|
) override {
|
||||||
std::vector<std::shared_ptr<Heightmap>> maps;
|
std::vector<std::shared_ptr<Heightmap>> maps;
|
||||||
|
|
||||||
|
uint biomeParameters = def.biomeParameters;
|
||||||
auto L = lua::get_main_thread();
|
auto L = lua::get_main_thread();
|
||||||
lua::pushenv(L, *env);
|
lua::pushenv(L, *env);
|
||||||
if (lua::getfield(L, "generate_biome_parameters")) {
|
if (lua::getfield(L, "generate_biome_parameters")) {
|
||||||
@ -79,7 +77,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<StructurePlacement> placeStructures(
|
std::vector<StructurePlacement> placeStructures(
|
||||||
const GeneratorDef& def,
|
|
||||||
const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed,
|
const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed,
|
||||||
const std::shared_ptr<Heightmap>& heightmap
|
const std::shared_ptr<Heightmap>& heightmap
|
||||||
) override {
|
) override {
|
||||||
@ -153,14 +150,6 @@ public:
|
|||||||
const std::vector<Biome>& getBiomes() const override {
|
const std::vector<Biome>& getBiomes() const override {
|
||||||
return biomes;
|
return biomes;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint getBiomeParameters() const override {
|
|
||||||
return biomeParameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint getSeaLevel() const override {
|
|
||||||
return seaLevel;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static BlocksLayer load_layer(
|
static BlocksLayer load_layer(
|
||||||
@ -273,7 +262,7 @@ static inline Biome load_biome(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GeneratorScript> scripting::load_generator(
|
std::unique_ptr<GeneratorScript> scripting::load_generator(
|
||||||
const fs::path& file
|
const GeneratorDef& def, const fs::path& file
|
||||||
) {
|
) {
|
||||||
auto env = create_environment();
|
auto env = create_environment();
|
||||||
auto L = lua::get_main_thread();
|
auto L = lua::get_main_thread();
|
||||||
@ -285,24 +274,20 @@ std::unique_ptr<GeneratorScript> scripting::load_generator(
|
|||||||
auto root = lua::tovalue(L, -1);
|
auto root = lua::tovalue(L, -1);
|
||||||
lua::pop(L);
|
lua::pop(L);
|
||||||
|
|
||||||
uint biomeParameters = root["biome_parameters"].asInteger();
|
|
||||||
uint seaLevel = 0;
|
|
||||||
root.at("sea_level").get(seaLevel);
|
|
||||||
|
|
||||||
std::vector<Biome> biomes;
|
std::vector<Biome> biomes;
|
||||||
|
|
||||||
const auto& biomesMap = root["biomes"];
|
const auto& biomesMap = root["biomes"];
|
||||||
for (const auto& [biomeName, biomeMap] : biomesMap.asObject()) {
|
for (const auto& [biomeName, biomeMap] : biomesMap.asObject()) {
|
||||||
try {
|
try {
|
||||||
biomes.push_back(
|
biomes.push_back(
|
||||||
load_biome(biomeMap, biomeName, biomeParameters, -2));
|
load_biome(biomeMap, biomeName, def.biomeParameters, -2));
|
||||||
} catch (const std::runtime_error& err) {
|
} catch (const std::runtime_error& err) {
|
||||||
throw std::runtime_error("biome "+biomeName+": "+err.what());
|
throw std::runtime_error("biome "+biomeName+": "+err.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::make_unique<LuaGeneratorScript>(
|
return std::make_unique<LuaGeneratorScript>(
|
||||||
|
def,
|
||||||
std::move(env),
|
std::move(env),
|
||||||
std::move(biomes),
|
std::move(biomes)
|
||||||
biomeParameters,
|
);
|
||||||
seaLevel);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -135,19 +135,12 @@ public:
|
|||||||
const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed) = 0;
|
const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed) = 0;
|
||||||
|
|
||||||
virtual std::vector<StructurePlacement> placeStructures(
|
virtual std::vector<StructurePlacement> placeStructures(
|
||||||
const GeneratorDef& def,
|
|
||||||
const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed,
|
const glm::ivec2& offset, const glm::ivec2& size, uint64_t seed,
|
||||||
const std::shared_ptr<Heightmap>& heightmap) = 0;
|
const std::shared_ptr<Heightmap>& heightmap) = 0;
|
||||||
|
|
||||||
/// @brief Get generator biomes
|
/// @brief Get generator biomes
|
||||||
virtual const std::vector<Biome>& getBiomes() const = 0;
|
virtual const std::vector<Biome>& getBiomes() const = 0;
|
||||||
|
|
||||||
/// @return Number of biome parameters, that biome choosing depending on
|
|
||||||
virtual uint getBiomeParameters() const = 0;
|
|
||||||
|
|
||||||
/// @return Sea level (top of seaLayers)
|
|
||||||
virtual uint getSeaLevel() const = 0;
|
|
||||||
|
|
||||||
/// @brief Build the runtime cache
|
/// @brief Build the runtime cache
|
||||||
/// @param content built content
|
/// @param content built content
|
||||||
virtual void prepare(const GeneratorDef& def, const Content* content) = 0;
|
virtual void prepare(const GeneratorDef& def, const Content* content) = 0;
|
||||||
@ -169,6 +162,12 @@ struct GeneratorDef {
|
|||||||
std::string name;
|
std::string name;
|
||||||
std::unique_ptr<GeneratorScript> script;
|
std::unique_ptr<GeneratorScript> script;
|
||||||
|
|
||||||
|
/// @brief Sea level (top of seaLayers)
|
||||||
|
uint seaLevel = 0;
|
||||||
|
|
||||||
|
/// @brief Number of biome parameters, that biome choosing depending on
|
||||||
|
uint biomeParameters = 0;
|
||||||
|
|
||||||
std::unordered_map<std::string, size_t> structuresIndices;
|
std::unordered_map<std::string, size_t> structuresIndices;
|
||||||
std::vector<std::unique_ptr<GeneratingVoxelStructure>> structures;
|
std::vector<std::unique_ptr<GeneratingVoxelStructure>> structures;
|
||||||
|
|
||||||
|
|||||||
@ -175,7 +175,7 @@ void WorldGenerator::generateStructures(
|
|||||||
const auto& heightmap = prototype.heightmap;
|
const auto& heightmap = prototype.heightmap;
|
||||||
|
|
||||||
util::concat(prototype.structures, def.script->placeStructures(
|
util::concat(prototype.structures, def.script->placeStructures(
|
||||||
def, {chunkX * CHUNK_W, chunkZ * CHUNK_D}, {CHUNK_W, CHUNK_D}, seed,
|
{chunkX * CHUNK_W, chunkZ * CHUNK_D}, {CHUNK_W, CHUNK_D}, seed,
|
||||||
heightmap
|
heightmap
|
||||||
));
|
));
|
||||||
for (const auto& placement : prototype.structures) {
|
for (const auto& placement : prototype.structures) {
|
||||||
@ -202,7 +202,7 @@ void WorldGenerator::generateStructures(
|
|||||||
}
|
}
|
||||||
uint8_t rotation = structsRand.randU32() % 4;
|
uint8_t rotation = structsRand.randU32() % 4;
|
||||||
int height = heights[z * CHUNK_W + x] * CHUNK_H;
|
int height = heights[z * CHUNK_W + x] * CHUNK_H;
|
||||||
if (height < def.script->getSeaLevel()) {
|
if (height < def.seaLevel) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto& structure = *def.structures[structureId]->fragments[rotation];
|
auto& structure = *def.structures[structureId]->fragments[rotation];
|
||||||
@ -268,7 +268,7 @@ void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
|
|||||||
const auto& prototype = requirePrototype(chunkX, chunkZ);
|
const auto& prototype = requirePrototype(chunkX, chunkZ);
|
||||||
const auto values = prototype.heightmap->getValues();
|
const auto values = prototype.heightmap->getValues();
|
||||||
|
|
||||||
uint seaLevel = def.script->getSeaLevel();
|
uint seaLevel = def.seaLevel;
|
||||||
|
|
||||||
std::memset(voxels, 0, sizeof(voxel) * CHUNK_VOL);
|
std::memset(voxels, 0, sizeof(voxel) * CHUNK_VOL);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user