Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Jul 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/lua-api-biome.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ ores = {
{
block = "default:iron_ore",
probability = 0.0003,
size = 8
size = 8,
gen_type = "flood_fill"
}
}
```
Expand All @@ -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`

Expand Down
11 changes: 9 additions & 2 deletions mods/default/biomes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}
},

Expand Down
10 changes: 8 additions & 2 deletions source/common/world/PlacementEntry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
};

Expand Down
7 changes: 7 additions & 0 deletions source/server/lua/loader/LuaBiomeLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>());
}
}
}
Expand Down
57 changes: 44 additions & 13 deletions source/server/world/TerrainGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions source/server/world/TerrainGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down