Add random walk as an alternative to flood fill for oregen (#148)

* Improved oregen
* [Lua API] Added biome ore definition property 'gen_type'.

Co-authored-by: Quentin Bazin <quent42340@gmail.com>
master
DeatHunter 2020-07-08 02:28:11 +02:00 committed by GitHub
parent 95233b78ad
commit 5ba2699c4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 18 deletions

View File

@ -183,7 +183,8 @@ ores = {
{
block = "default:iron_ore",
probability = 0.0003,
size = 8
size = 8,
gen_type = "flood_fill"
}
}
```
@ -193,6 +194,7 @@ Possible attributes:
- `block`: Ore block to be used
- `probability`: Probability to spawn an ore vein with that block
- `size`: Ore vein size
- `gen_type`: Algorithm used for generation (possible values: `flood_fill`, `random_walk`)
### `params`

View File

@ -57,10 +57,17 @@ mod:biome {
-- could decide whether ores at a point very far down should
-- still depend on the surface biome, or only on the worldtype.
ores = {
{
block = "default:coal_ore",
probability = 0.001,
size = 2,
gen_type = "flood_fill",
},
{
block = "default:iron_ore",
probability = 0.0003,
size = 8
probability = 0.003,
size = 8,
gen_type = "random_walk",
}
},

View File

@ -49,16 +49,22 @@ struct Flora : public gk::ISerializable {
};
struct Ore : public gk::ISerializable {
enum Gen {
RandomWalk,
FloodFill
};
u16 blockID;
double probability;
double size;
u8 genType;
void serialize(sf::Packet &packet) const override {
packet << blockID << probability << size;
packet << blockID << probability << size << genType;
}
void deserialize(sf::Packet &packet) override {
packet >> blockID >> probability >> size;
packet >> blockID >> probability >> size >> genType;
}
};

View File

@ -143,6 +143,13 @@ inline void LuaBiomeLoader::loadOrePlacementEntries(Biome &biome, const sol::tab
oreEntry.blockID = Registry::getInstance().getBlockFromStringID(oreDefinition["block"]).id();
oreEntry.probability = oreDefinition["probability"];
oreEntry.size = oreDefinition["size"];
std::unordered_map<std::string, PlacementEntry::Ore::Gen> genTypes{
{"random_walk", PlacementEntry::Ore::Gen::RandomWalk},
{"flood_fill", PlacementEntry::Ore::Gen::FloodFill},
};
oreEntry.genType = genTypes.at(oreDefinition["gen_type"].get<std::string>());
}
}
}

View File

@ -84,12 +84,12 @@ void TerrainGenerator::fastNoiseGeneration(ServerChunk &chunk) const {
else
chunk.setBlockRaw(x, y, z, biome.getDeepBlockID());
// Populate ores.
generateOres(chunk, x, y, z, biome, rand);
// Caves
generateCaves(chunk, x, y, z, h);
// Populate ores.
generateOres(chunk, x, y, z, biome, rand);
// Generate trees, flora and portals
if (isGeneratingTopBlock && chunk.getBlock(x, y, z)) {
// Try to place a tree
@ -199,20 +199,39 @@ inline void TerrainGenerator::generateOres(ServerChunk &chunk, int x, int y, int
if (!rand.get<bool>(ore.probability))
continue;
oreFloodFill(chunk, x, y, z, biome.getDeepBlockID(), ore.blockID, 2, rand);
if (ore.genType == PlacementEntry::Ore::Gen::RandomWalk)
randomWalkOrePlace(chunk, x, y, z, rand, ore.blockID, biome.getDeepBlockID(), ore.size);
else if (ore.genType == PlacementEntry::Ore::Gen::FloodFill)
oreFloodFill(chunk, x, y, z, biome.getDeepBlockID(), ore.blockID, ore.size, rand);
break;
}
}
inline void TerrainGenerator::generateCaves(ServerChunk &chunk, int x, int y, int z, int h) const {
float n2 = noise2d(-(x + chunk.x() * CHUNK_WIDTH) / 256.0, (y + chunk.y() * CHUNK_DEPTH) / 256.0, 8, 0.3) * 4;
float r2 = noise3d_abs(-(x + chunk.x() * CHUNK_WIDTH) / 512.0f, (z + chunk.z() * CHUNK_HEIGHT) / 512.0f, (y + chunk.y() * CHUNK_DEPTH) / 512.0f, 4, 0.1);
float r3 = noise3d_abs(-(x + chunk.x() * CHUNK_WIDTH) / 512.0f, (z + chunk.z() * CHUNK_HEIGHT) / 128.0f, (y + chunk.y() * CHUNK_DEPTH) / 512.0f, 4, 1);
float r4 = n2 * 5 + r2 * r3 * 20;
if (r4 > 6 && r4 < 8 && h > SEALEVEL) {
chunk.setBlockRaw(x, y, z - 1, 0);
chunk.setBlockRaw(x, y, z, 0);
chunk.setBlockRaw(x, y, z + 1, 0);
inline void TerrainGenerator::randomWalkOrePlace(ServerChunk &chunk, int x, int y, int z, Random_t &rand, u16 oreBlock, u16 deepBlock, int size) const {
if (size <= 0 || chunk.getBlock(x, y, z) != deepBlock)
return;
chunk.setBlockRaw(x, y, z, oreBlock);
int direction = rand.get(1, 6);
switch(direction) {
case 1:
randomWalkOrePlace(chunk, x + 1, y, z, rand, oreBlock, deepBlock, size - 1);
break;
case 2:
randomWalkOrePlace(chunk, x - 1, y, z, rand, oreBlock, deepBlock, size - 1);
break;
case 3:
randomWalkOrePlace(chunk, x, y + 1, z, rand, oreBlock, deepBlock, size - 1);
break;
case 4:
randomWalkOrePlace(chunk, x, y - 1, z, rand, oreBlock, deepBlock, size - 1);
break;
case 5:
randomWalkOrePlace(chunk, x, y, z + 1, rand, oreBlock, deepBlock, size - 1);
break;
case 6:
randomWalkOrePlace(chunk, x, y, z - 1, rand, oreBlock, deepBlock, size - 1);
break;
}
}
@ -247,6 +266,18 @@ void TerrainGenerator::oreFloodFill(ServerChunk &chunk, double x, double y, doub
oreFloodFill(chunk, x - 1, y - 1, z - 1, toReplace, replaceWith, depth - 1, rand);
}
inline void TerrainGenerator::generateCaves(ServerChunk &chunk, int x, int y, int z, int h) const {
float n2 = noise2d(-(x + chunk.x() * CHUNK_WIDTH) / 256.0, (y + chunk.y() * CHUNK_DEPTH) / 256.0, 8, 0.3) * 4;
float r2 = noise3d_abs(-(x + chunk.x() * CHUNK_WIDTH) / 512.0f, (z + chunk.z() * CHUNK_HEIGHT) / 512.0f, (y + chunk.y() * CHUNK_DEPTH) / 512.0f, 4, 0.1);
float r3 = noise3d_abs(-(x + chunk.x() * CHUNK_WIDTH) / 512.0f, (z + chunk.z() * CHUNK_HEIGHT) / 128.0f, (y + chunk.y() * CHUNK_DEPTH) / 512.0f, 4, 1);
float r4 = n2 * 5 + r2 * r3 * 20;
if (r4 > 6 && r4 < 8 && h > SEALEVEL) {
chunk.setBlockRaw(x, y, z - 1, 0);
chunk.setBlockRaw(x, y, z, 0);
chunk.setBlockRaw(x, y, z + 1, 0);
}
}
inline float TerrainGenerator::noise2d(double x, double y, int octaves, float persistence) {
float sum = 0;
float strength = 1.0;

View File

@ -57,7 +57,9 @@ class TerrainGenerator {
void generateOres(ServerChunk &chunk, int x, int y, int z, const Biome &biome, Random_t &rand) const;
void generateCaves(ServerChunk &chunk, int x, int y, int z, int h) const;
void randomWalkOrePlace(ServerChunk &chunk, int x, int y, int z, Random_t &rand, u16 oreBlock, u16 deepBlock, int size) const;
void oreFloodFill(ServerChunk &chunk, double x, double y, double z, u16 toReplace, u16 replaceWith, int depth, Random_t &rand) const;
static float noise2d(double x, double y, int octaves, float persistence);
static float noise3d_abs(double x, double y, double z, int octaves, float persistence);