diff --git a/src/logic/scripting/scripting_world_generation.cpp b/src/logic/scripting/scripting_world_generation.cpp index 0f704e7e..94fceb7b 100644 --- a/src/logic/scripting/scripting_world_generation.cpp +++ b/src/logic/scripting/scripting_world_generation.cpp @@ -149,6 +149,36 @@ static inline BlocksLayers load_layers( return BlocksLayers {std::move(layers), lastLayersHeight}; } +static inline BiomePlants load_plants(lua::State* L) { + float plantChance = lua::get_number_field(L, "plant_chance", 0.0); + float plantsWeightSum = 0.0f; + std::vector plants; + if (lua::getfield(L, "plants")) { + if (!lua::istable(L, -1)) { + throw std::runtime_error("'plants' must be a table"); + } + int plantsCount = lua::objlen(L, -1); + for (int i = 1; i <= plantsCount; i++) { + 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) { + throw std::runtime_error("weight must be positive"); + } + plantsWeightSum += weight; + plants.push_back(PlantEntry {block, weight, {}}); + lua::pop(L); + } + lua::pop(L); + } + std::sort(plants.begin(), plants.end(), std::greater()); + return BiomePlants { + std::move(plants), plantsWeightSum, plantChance}; +} + static inline Biome load_biome( lua::State* L, const std::string& name, uint parametersCount, int idx ) { @@ -169,37 +199,14 @@ static inline Biome load_biome( } lua::pop(L); - float plantChance = lua::get_number_field(L, "plant_chance", 0.0); - float plantsWeightSum = 0.0f; - std::vector plants; - if (lua::getfield(L, "plants")) { - if (!lua::istable(L, -1)) { - throw std::runtime_error("'plants' must be a table"); - } - int plantsCount = lua::objlen(L, -1); - for (int i = 1; i <= plantsCount; i++) { - 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"); - // TODO: range check (positive) - plantsWeightSum += weight; - plants.push_back(PlantEntry {block, weight, {}}); - lua::pop(L); - } - lua::pop(L); - } - std::sort(plants.begin(), plants.end(), std::greater()); - + BiomePlants plants = load_plants(L); BlocksLayers groundLayers = load_layers(L, "layers"); BlocksLayers seaLayers = load_layers(L, "sea_layers"); lua::pop(L); return Biome { name, std::move(parameters), - BiomePlants {plants, plantsWeightSum, plantChance}, + std::move(plants), std::move(groundLayers), std::move(seaLayers)}; } diff --git a/src/world/generator/WorldGenerator.cpp b/src/world/generator/WorldGenerator.cpp index be44f6f3..1ffcfef5 100644 --- a/src/world/generator/WorldGenerator.cpp +++ b/src/world/generator/WorldGenerator.cpp @@ -110,8 +110,8 @@ void WorldGenerator::generate( generate_pole(groundLayers, height, 0, seaLevel, voxels, x, z); if (height+1 > seaLevel) { - // TODO: add underwater plants support - float rand = (plantsRand.randU32() % RAND_MAX) / static_cast(RAND_MAX); + float rand = (plantsRand.randU32() % RAND_MAX) / + static_cast(RAND_MAX); blockid_t plant = biome->plants.choose(rand); if (plant) { voxels[vox_index(x, height+1, z)].id = plant;