refactor: use dynamic::* for parsing
This commit is contained in:
@@ -10,10 +10,9 @@
|
|||||||
#include "content/Content.hpp"
|
#include "content/Content.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "voxels/Chunk.hpp"
|
#include "voxels/Chunk.hpp"
|
||||||
|
#include "data/dynamic.hpp"
|
||||||
#include "world/generator/GeneratorDef.hpp"
|
#include "world/generator/GeneratorDef.hpp"
|
||||||
|
|
||||||
// TODO: use dynamic::* for parsing
|
|
||||||
|
|
||||||
class LuaGeneratorScript : public GeneratorScript {
|
class LuaGeneratorScript : public GeneratorScript {
|
||||||
scriptenv env;
|
scriptenv env;
|
||||||
std::vector<Biome> biomes;
|
std::vector<Biome> biomes;
|
||||||
@@ -106,11 +105,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static BlocksLayer load_layer(
|
static BlocksLayer load_layer(
|
||||||
lua::State* L, int idx, uint& lastLayersHeight, bool& hasResizeableLayer
|
const dynamic::Map_sptr& map, int idx, uint& lastLayersHeight, bool& hasResizeableLayer
|
||||||
) {
|
) {
|
||||||
auto name = lua::require_string_field(L, "block");
|
auto name = map->get<std::string>("block");
|
||||||
int height = lua::require_integer_field(L, "height");
|
int height = map->get<integer_t>("height");
|
||||||
bool belowSeaLevel = lua::get_boolean_field(L, "below_sea_level", true);
|
bool belowSeaLevel = map->get("below_sea_level", true);
|
||||||
|
|
||||||
if (hasResizeableLayer) {
|
if (hasResizeableLayer) {
|
||||||
lastLayersHeight += height;
|
lastLayersHeight += height;
|
||||||
@@ -125,54 +124,44 @@ static BlocksLayer load_layer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline BlocksLayers load_layers(
|
static inline BlocksLayers load_layers(
|
||||||
lua::State* L, const std::string& fieldname
|
const dynamic::List_sptr& layersArr, const std::string& fieldname
|
||||||
) {
|
) {
|
||||||
uint lastLayersHeight = 0;
|
uint lastLayersHeight = 0;
|
||||||
bool hasResizeableLayer = false;
|
bool hasResizeableLayer = false;
|
||||||
std::vector<BlocksLayer> layers;
|
std::vector<BlocksLayer> layers;
|
||||||
|
|
||||||
if (lua::getfield(L, fieldname)) {
|
for (int i = 0; i < layersArr->size(); i++) {
|
||||||
int len = lua::objlen(L, -1);
|
const auto& layerMap = layersArr->map(i);
|
||||||
for (int i = 1; i <= len; i++) {
|
try {
|
||||||
lua::rawgeti(L, i);
|
layers.push_back(
|
||||||
try {
|
load_layer(layerMap, -1, lastLayersHeight, hasResizeableLayer));
|
||||||
layers.push_back(
|
} catch (const std::runtime_error& err) {
|
||||||
load_layer(L, -1, lastLayersHeight, hasResizeableLayer));
|
throw std::runtime_error(
|
||||||
} catch (const std::runtime_error& err) {
|
fieldname+" #"+std::to_string(i)+": "+err.what());
|
||||||
throw std::runtime_error(
|
|
||||||
fieldname+" #"+std::to_string(i)+": "+err.what());
|
|
||||||
}
|
|
||||||
lua::pop(L);
|
|
||||||
}
|
}
|
||||||
lua::pop(L);
|
|
||||||
}
|
}
|
||||||
return BlocksLayers {std::move(layers), lastLayersHeight};
|
return BlocksLayers {std::move(layers), lastLayersHeight};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline BiomePlants load_plants(lua::State* L) {
|
static inline BiomePlants load_plants(
|
||||||
float plantChance = lua::get_number_field(L, "plant_chance", 0.0);
|
const dynamic::Map_sptr& biomeMap
|
||||||
|
) {
|
||||||
|
float plantChance = biomeMap->get("plant_chance", 0.0);
|
||||||
float plantsWeightSum = 0.0f;
|
float plantsWeightSum = 0.0f;
|
||||||
|
|
||||||
std::vector<PlantEntry> plants;
|
std::vector<PlantEntry> plants;
|
||||||
if (lua::getfield(L, "plants")) {
|
if (biomeMap->has("plants")) {
|
||||||
if (!lua::istable(L, -1)) {
|
auto plantsArr = biomeMap->list("plants");
|
||||||
throw std::runtime_error("'plants' must be a table");
|
for (size_t i = 0; i < plantsArr->size(); i++) {
|
||||||
}
|
auto entry = plantsArr->map(i);
|
||||||
int plantsCount = lua::objlen(L, -1);
|
auto block = entry->get<std::string>("block");
|
||||||
for (int i = 1; i <= plantsCount; i++) {
|
float weight = entry->get<number_t>("weight");
|
||||||
lua::rawgeti(L, i);
|
|
||||||
if (!lua::istable(L, -1)) {
|
|
||||||
throw std::runtime_error("plant must be a table");
|
|
||||||
}
|
|
||||||
auto block = lua::require_string_field(L, "block");
|
|
||||||
float weight = lua::require_number_field(L, "weight");
|
|
||||||
if (weight <= 0.0f) {
|
if (weight <= 0.0f) {
|
||||||
throw std::runtime_error("weight must be positive");
|
throw std::runtime_error("weight must be positive");
|
||||||
}
|
}
|
||||||
plantsWeightSum += weight;
|
plantsWeightSum += weight;
|
||||||
plants.push_back(PlantEntry {block, weight, {}});
|
plants.push_back(PlantEntry {block, weight, {}});
|
||||||
lua::pop(L);
|
|
||||||
}
|
}
|
||||||
lua::pop(L);
|
|
||||||
}
|
}
|
||||||
std::sort(plants.begin(), plants.end(), std::greater<PlantEntry>());
|
std::sort(plants.begin(), plants.end(), std::greater<PlantEntry>());
|
||||||
return BiomePlants {
|
return BiomePlants {
|
||||||
@@ -180,29 +169,28 @@ static inline BiomePlants load_plants(lua::State* L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline Biome load_biome(
|
static inline Biome load_biome(
|
||||||
lua::State* L, const std::string& name, uint parametersCount, int idx
|
const dynamic::Map_sptr& biomeMap,
|
||||||
|
const std::string& name,
|
||||||
|
uint parametersCount,
|
||||||
|
int idx
|
||||||
) {
|
) {
|
||||||
lua::pushvalue(L, idx);
|
|
||||||
|
|
||||||
std::vector<BiomeParameter> parameters;
|
std::vector<BiomeParameter> parameters;
|
||||||
lua::requirefield(L, "parameters");
|
|
||||||
if (lua::objlen(L, -1) < parametersCount) {
|
const auto& paramsArr = biomeMap->list("parameters");
|
||||||
|
if (paramsArr->size() < parametersCount) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
std::to_string(parametersCount)+" parameters expected");
|
std::to_string(parametersCount)+" parameters expected");
|
||||||
}
|
}
|
||||||
for (uint i = 1; i <= parametersCount; i++) {
|
for (size_t i = 0; i < parametersCount; i++) {
|
||||||
lua::rawgeti(L, i);
|
const auto& paramMap = paramsArr->map(i);
|
||||||
float value = lua::require_number_field(L, "value");
|
float value = paramMap->get<number_t>("value");
|
||||||
float weight = lua::require_number_field(L, "weight");
|
float weight = paramMap->get<number_t>("weight");
|
||||||
parameters.push_back(BiomeParameter {value, weight});
|
parameters.push_back(BiomeParameter {value, weight});
|
||||||
lua::pop(L);
|
|
||||||
}
|
}
|
||||||
lua::pop(L);
|
|
||||||
|
|
||||||
BiomePlants plants = load_plants(L);
|
BiomePlants plants = load_plants(biomeMap);
|
||||||
BlocksLayers groundLayers = load_layers(L, "layers");
|
BlocksLayers groundLayers = load_layers(biomeMap->list("layers"), "layers");
|
||||||
BlocksLayers seaLayers = load_layers(L, "sea_layers");
|
BlocksLayers seaLayers = load_layers(biomeMap->list("sea_layers"), "sea_layers");
|
||||||
lua::pop(L);
|
|
||||||
return Biome {
|
return Biome {
|
||||||
name,
|
name,
|
||||||
std::move(parameters),
|
std::move(parameters),
|
||||||
@@ -221,30 +209,26 @@ std::unique_ptr<GeneratorScript> scripting::load_generator(
|
|||||||
lua::pop(L, load_script(*env, "generator", file));
|
lua::pop(L, load_script(*env, "generator", file));
|
||||||
|
|
||||||
lua::pushenv(L, *env);
|
lua::pushenv(L, *env);
|
||||||
|
auto val = lua::tovalue(L, -1);
|
||||||
|
lua::pop(L);
|
||||||
|
|
||||||
|
auto root = std::get<dynamic::Map_sptr>(val);
|
||||||
|
|
||||||
uint biomeParameters = lua::get_integer_field(L, "biome_parameters", 0, 0, 16);
|
uint biomeParameters = lua::get_integer_field(L, "biome_parameters", 0, 0, 16);
|
||||||
uint seaLevel = lua::get_integer_field(L, "sea_level", 0, 0, CHUNK_H);
|
uint seaLevel = lua::get_integer_field(L, "sea_level", 0, 0, CHUNK_H);
|
||||||
|
|
||||||
std::vector<Biome> biomes;
|
std::vector<Biome> biomes;
|
||||||
lua::requirefield(L, "biomes");
|
|
||||||
if (!lua::istable(L, -1)) {
|
const auto& biomesMap = root->map("biomes");
|
||||||
throw std::runtime_error("'biomes' must be a table");
|
for (const auto& [biomeName, value] : biomesMap->values) {
|
||||||
}
|
const auto& biomeMap = std::get<dynamic::Map_sptr>(value);
|
||||||
lua::pushnil(L);
|
|
||||||
while (lua::next(L, -2)) {
|
|
||||||
lua::pushvalue(L, -2);
|
|
||||||
std::string biomeName = lua::tostring(L, -1);
|
|
||||||
try {
|
try {
|
||||||
biomes.push_back(
|
biomes.push_back(
|
||||||
load_biome(L, biomeName, biomeParameters, -2));
|
load_biome(biomeMap, biomeName, 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());
|
||||||
}
|
}
|
||||||
lua::pop(L, 2);
|
|
||||||
}
|
}
|
||||||
lua::pop(L);
|
|
||||||
|
|
||||||
lua::pop(L);
|
|
||||||
return std::make_unique<LuaGeneratorScript>(
|
return std::make_unique<LuaGeneratorScript>(
|
||||||
std::move(env),
|
std::move(env),
|
||||||
std::move(biomes),
|
std::move(biomes),
|
||||||
|
|||||||
Reference in New Issue
Block a user