fix caves issues & add block 'surface-replacement' property
This commit is contained in:
parent
c022e11c3b
commit
b4578cfb87
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"texture": "dirt",
|
"texture": "dirt",
|
||||||
"material": "base:ground"
|
"material": "base:ground",
|
||||||
}
|
"surface-replacement": "base:grass_block"
|
||||||
|
}
|
||||||
|
|||||||
@ -82,6 +82,7 @@ std::unique_ptr<Content> ContentBuilder::build() {
|
|||||||
// Now, it's time to resolve foreign keys
|
// Now, it's time to resolve foreign keys
|
||||||
for (Block* def : blockDefsIndices) {
|
for (Block* def : blockDefsIndices) {
|
||||||
def->rt.pickingItem = content->items.require(def->pickingItem).rt.id;
|
def->rt.pickingItem = content->items.require(def->pickingItem).rt.id;
|
||||||
|
def->rt.surfaceReplacement = content->blocks.require(def->surfaceReplacement).rt.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ItemDef* def : itemDefsIndices) {
|
for (ItemDef* def : itemDefsIndices) {
|
||||||
|
|||||||
@ -286,6 +286,7 @@ void ContentLoader::loadBlock(
|
|||||||
root.at("hidden").get(def.hidden);
|
root.at("hidden").get(def.hidden);
|
||||||
root.at("draw-group").get(def.drawGroup);
|
root.at("draw-group").get(def.drawGroup);
|
||||||
root.at("picking-item").get(def.pickingItem);
|
root.at("picking-item").get(def.pickingItem);
|
||||||
|
root.at("surface-replacement").get(def.surfaceReplacement);
|
||||||
root.at("script-name").get(def.scriptName);
|
root.at("script-name").get(def.scriptName);
|
||||||
root.at("ui-layout").get(def.uiLayout);
|
root.at("ui-layout").get(def.uiLayout);
|
||||||
root.at("inventory-size").get(def.inventorySize);
|
root.at("inventory-size").get(def.inventorySize);
|
||||||
|
|||||||
@ -74,8 +74,8 @@ namespace util {
|
|||||||
/// @note glm::distance2 does not support integer vectors
|
/// @note glm::distance2 does not support integer vectors
|
||||||
inline int distance2(const glm::ivec3& a, const glm::ivec3& b) {
|
inline int distance2(const glm::ivec3& a, const glm::ivec3& b) {
|
||||||
return (b.x - a.x) * (b.x - a.x) +
|
return (b.x - a.x) * (b.x - a.x) +
|
||||||
(b.y - a.y) * (b.y - a.y) +
|
(b.y - a.y) * (b.y - a.y) +
|
||||||
(b.z - a.z) * (b.z - a.z);
|
(b.z - a.z) * (b.z - a.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @return integer square of distance between two points
|
/// @return integer square of distance between two points
|
||||||
|
|||||||
@ -181,6 +181,9 @@ public:
|
|||||||
/// @brief Block script name in blocks/ without extension
|
/// @brief Block script name in blocks/ without extension
|
||||||
std::string scriptName = name.substr(name.find(':') + 1);
|
std::string scriptName = name.substr(name.find(':') + 1);
|
||||||
|
|
||||||
|
/// @brief Block will be used instead of this if generated on surface
|
||||||
|
std::string surfaceReplacement = name;
|
||||||
|
|
||||||
/// @brief Default block layout will be used by hud.open_block(...)
|
/// @brief Default block layout will be used by hud.open_block(...)
|
||||||
std::string uiLayout = name;
|
std::string uiLayout = name;
|
||||||
|
|
||||||
@ -214,6 +217,8 @@ public:
|
|||||||
|
|
||||||
/// @brief picking item integer id
|
/// @brief picking item integer id
|
||||||
itemid_t pickingItem = 0;
|
itemid_t pickingItem = 0;
|
||||||
|
|
||||||
|
blockid_t surfaceReplacement = 0;
|
||||||
} rt {};
|
} rt {};
|
||||||
|
|
||||||
Block(const std::string& name);
|
Block(const std::string& name);
|
||||||
|
|||||||
@ -305,6 +305,65 @@ void WorldGenerator::update(int centerX, int centerY, int loadDistance) {
|
|||||||
surroundMap.setCenter(centerX, centerY);
|
surroundMap.setCenter(centerX, centerY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldGenerator::generatePlants(
|
||||||
|
const ChunkPrototype& prototype,
|
||||||
|
float* heights,
|
||||||
|
voxel* voxels,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
const Biome** biomes
|
||||||
|
) {
|
||||||
|
const auto& indices = content->getIndices()->blocks;
|
||||||
|
util::PseudoRandom plantsRand;
|
||||||
|
plantsRand.setSeed(chunkX, chunkZ);
|
||||||
|
|
||||||
|
for (uint z = 0; z < CHUNK_D; z++) {
|
||||||
|
for (uint x = 0; x < CHUNK_W; x++) {
|
||||||
|
const Biome* biome = biomes[z * CHUNK_W + x];
|
||||||
|
|
||||||
|
int height = heights[z * CHUNK_W + x] * CHUNK_H;
|
||||||
|
height = std::max(0, height);
|
||||||
|
|
||||||
|
if (height+1 > def.seaLevel) {
|
||||||
|
float rand = plantsRand.randFloat();
|
||||||
|
blockid_t plant = biome->plants.choose(rand);
|
||||||
|
if (plant) {
|
||||||
|
auto& voxel = voxels[vox_index(x, height+1, z)];
|
||||||
|
auto& groundVoxel = voxels[vox_index(x, height, z)];
|
||||||
|
if (indices.get(groundVoxel.id)->rt.solid) {
|
||||||
|
voxel = {plant, {}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldGenerator::generateLand(
|
||||||
|
const ChunkPrototype& prototype,
|
||||||
|
float* values,
|
||||||
|
voxel* voxels,
|
||||||
|
int chunkX,
|
||||||
|
int chunkZ,
|
||||||
|
const Biome** biomes
|
||||||
|
) {
|
||||||
|
uint seaLevel = def.seaLevel;
|
||||||
|
for (uint z = 0; z < CHUNK_D; z++) {
|
||||||
|
for (uint x = 0; x < CHUNK_W; x++) {
|
||||||
|
const Biome* biome = biomes[z * CHUNK_W + x];
|
||||||
|
|
||||||
|
int height = values[z * CHUNK_W + x] * CHUNK_H;
|
||||||
|
height = std::max(0, height);
|
||||||
|
|
||||||
|
const auto& groundLayers = biome->groundLayers;
|
||||||
|
const auto& seaLayers = biome->seaLayers;
|
||||||
|
|
||||||
|
generate_pole(seaLayers, seaLevel, height, seaLevel, voxels, x, z);
|
||||||
|
generate_pole(groundLayers, height, 0, seaLevel, voxels, x, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
|
void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
|
||||||
surroundMap.completeAt(chunkX, chunkZ);
|
surroundMap.completeAt(chunkX, chunkZ);
|
||||||
|
|
||||||
@ -315,9 +374,7 @@ void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
|
|||||||
|
|
||||||
std::memset(voxels, 0, sizeof(voxel) * CHUNK_VOL);
|
std::memset(voxels, 0, sizeof(voxel) * CHUNK_VOL);
|
||||||
|
|
||||||
util::PseudoRandom plantsRand;
|
const auto& indices = content->getIndices()->blocks;
|
||||||
plantsRand.setSeed(chunkX, chunkZ);
|
|
||||||
|
|
||||||
const auto& biomes = prototype.biomes.get();
|
const auto& biomes = prototype.biomes.get();
|
||||||
for (uint z = 0; z < CHUNK_D; z++) {
|
for (uint z = 0; z < CHUNK_D; z++) {
|
||||||
for (uint x = 0; x < CHUNK_W; x++) {
|
for (uint x = 0; x < CHUNK_W; x++) {
|
||||||
@ -331,18 +388,20 @@ void WorldGenerator::generate(voxel* voxels, int chunkX, int chunkZ) {
|
|||||||
|
|
||||||
generate_pole(seaLayers, seaLevel, height, seaLevel, voxels, x, z);
|
generate_pole(seaLayers, seaLevel, height, seaLevel, voxels, x, z);
|
||||||
generate_pole(groundLayers, height, 0, seaLevel, voxels, x, z);
|
generate_pole(groundLayers, height, 0, seaLevel, voxels, x, z);
|
||||||
|
|
||||||
if (height+1 > seaLevel) {
|
|
||||||
float rand = plantsRand.randFloat();
|
|
||||||
blockid_t plant = biome->plants.choose(rand);
|
|
||||||
if (plant) {
|
|
||||||
voxels[vox_index(x, height+1, z)].id = plant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
generateLines(prototype, voxels, chunkX, chunkZ);
|
generateLines(prototype, voxels, chunkX, chunkZ);
|
||||||
|
generatePlants(prototype, values, voxels, chunkX, chunkZ, biomes);
|
||||||
generateStructures(prototype, voxels, chunkX, chunkZ);
|
generateStructures(prototype, voxels, chunkX, chunkZ);
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||||
|
blockid_t id = voxels[i].id;
|
||||||
|
if (indices.get(id) == nullptr) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldGenerator::generateStructures(
|
void WorldGenerator::generateStructures(
|
||||||
@ -391,11 +450,12 @@ void WorldGenerator::generateStructures(
|
|||||||
void WorldGenerator::generateLines(
|
void WorldGenerator::generateLines(
|
||||||
const ChunkPrototype& prototype, voxel* voxels, int chunkX, int chunkZ
|
const ChunkPrototype& prototype, voxel* voxels, int chunkX, int chunkZ
|
||||||
) {
|
) {
|
||||||
|
const auto& indices = content->getIndices()->blocks;
|
||||||
for (const auto& line : prototype.lines) {
|
for (const auto& line : prototype.lines) {
|
||||||
int cgx = chunkX * CHUNK_W;
|
int cgx = chunkX * CHUNK_W;
|
||||||
int cgz = chunkZ * CHUNK_D;
|
int cgz = chunkZ * CHUNK_D;
|
||||||
|
|
||||||
int radius = line.radius;
|
int const radius = line.radius;
|
||||||
|
|
||||||
auto a = line.a;
|
auto a = line.a;
|
||||||
auto b = line.b;
|
auto b = line.b;
|
||||||
@ -418,8 +478,21 @@ void WorldGenerator::generateLines(
|
|||||||
glm::ivec3 closest = util::closest_point_on_segment(
|
glm::ivec3 closest = util::closest_point_on_segment(
|
||||||
a, b, point
|
a, b, point
|
||||||
);
|
);
|
||||||
if (util::distance2(closest, point) <= radius*radius) {
|
if (y > 0 && util::distance2(closest, point) <= radius*radius && line.block == BLOCK_AIR) {
|
||||||
voxels[vox_index(x, y, z)] = {line.block, {}};
|
auto& voxel = voxels[vox_index(x, y, z)];
|
||||||
|
if (!indices.require(voxel.id).replaceable) {
|
||||||
|
voxel = {line.block, {}};
|
||||||
|
}
|
||||||
|
auto& below = voxels[vox_index(x, y-1, z)];
|
||||||
|
glm::ivec3 closest2 = util::closest_point_on_segment(
|
||||||
|
a, b, {gx, y-1, gz}
|
||||||
|
);
|
||||||
|
if (util::distance2(closest2, {gx, y-1, gz}) > radius*radius) {
|
||||||
|
const auto& def = indices.require(below.id);
|
||||||
|
if (def.rt.surfaceReplacement != below.id) {
|
||||||
|
below = {def.rt.surfaceReplacement, {}};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,6 +83,22 @@ class WorldGenerator {
|
|||||||
void generateStructures(
|
void generateStructures(
|
||||||
const ChunkPrototype& prototype, voxel* voxels, int x, int z
|
const ChunkPrototype& prototype, voxel* voxels, int x, int z
|
||||||
);
|
);
|
||||||
|
void generatePlants(
|
||||||
|
const ChunkPrototype& prototype,
|
||||||
|
float* values,
|
||||||
|
voxel* voxels,
|
||||||
|
int x,
|
||||||
|
int z,
|
||||||
|
const Biome** biomes
|
||||||
|
);
|
||||||
|
void generateLand(
|
||||||
|
const ChunkPrototype& prototype,
|
||||||
|
float* values,
|
||||||
|
voxel* voxels,
|
||||||
|
int x,
|
||||||
|
int z,
|
||||||
|
const Biome** biomes
|
||||||
|
);
|
||||||
public:
|
public:
|
||||||
WorldGenerator(
|
WorldGenerator(
|
||||||
const GeneratorDef& def,
|
const GeneratorDef& def,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user