From 0369d07996e1bbdf194568b15177a05ddca9761c Mon Sep 17 00:00:00 2001 From: DualFroz Date: Tue, 8 Sep 2026 19:00:22 +0200 Subject: [PATCH] feat: extend NetherGen --- core/src/NetherGen.cpp | 139 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/core/src/NetherGen.cpp b/core/src/NetherGen.cpp index 498ee3d..1ed97b1 100644 --- a/core/src/NetherGen.cpp +++ b/core/src/NetherGen.cpp @@ -157,3 +157,142 @@ Block NetherGenerator::blockAt(const NetherColumn& column, int gx, int gy, int g else if (depth <= 3) material = fillerFor(column.biome); } + float qf = params.quartzFrequency; + float vein = oreNoise.noise3D(gx * qf, gy * qf, gz * qf); + if (material == Block::Netherrack) { + if (vein > params.quartzThreshold) material = Block::NetherQuartzOre; + else if (vein < -0.78f && column.biome == NetherBiome::BasaltDeltas) + material = Block::Blackstone; + } + + if (gy >= column.ceilingHeight && gy <= column.ceilingHeight + 2) { + float glow = oreNoise.noise3D(gx * 0.09f + 53.1f, gy * 0.09f - 21.7f, gz * 0.09f + 11.9f); + if (glow > 0.66f) material = Block::Glowstone; + } + + if (gy >= column.floorHeight - 1 && gy <= column.floorHeight && + gy >= params.lavaLevel - 1 && gy <= params.lavaLevel + 2 && vein > 0.30f) { + material = Block::Magma; + } + + return material; +} + +void NetherGenerator::generateChunk(Chunk& chunk, const Vec3i& chunkCoord) const { + int ox = chunkCoord.x * chunkSize; + int oy = chunkCoord.y * chunkSize; + int oz = chunkCoord.z * chunkSize; + + for (int lx = 0; lx < chunkSize; ++lx) { + for (int lz = 0; lz < chunkSize; ++lz) { + NetherColumn column = columnAt(ox + lx, oz + lz); + for (int ly = 0; ly < chunkSize; ++ly) + chunk.set(lx, ly, lz, blockAt(column, ox + lx, oy + ly, oz + lz)); + } + } +} + +void NetherGenerator::generateColumn(World& world, int columnX, int columnZ) const { + for (int cy = 0; cy < stackChunkCount(); ++cy) { + Chunk& chunk = world.ensureChunk({columnX, cy, columnZ}); + generateChunk(chunk, {columnX, cy, columnZ}); + } + if (params.decorate) decorateColumn(world, columnX, columnZ); +} + +void NetherGenerator::raiseBasaltPillar(World& world, int gx, int gz, const NetherColumn& column, + uint32_t roll) const { + int base = column.floorHeight + 1; + if (base <= params.lavaLevel) base = params.lavaLevel + 1; + int tall = 3 + static_cast((roll >> 4) % 10u); + int top = base + tall; + if (top >= column.ceilingHeight) top = column.ceilingHeight - 1; + + for (int y = base; y <= top; ++y) { + if (!replaceable(world.blockAt(gx, y, gz))) break; + world.setBlock(gx, y, gz, Block::Basalt); + } + if ((roll & 3u) == 0u && replaceable(world.blockAt(gx, base - 1, gz))) + world.setBlock(gx, base - 1, gz, Block::Magma); +} + +void NetherGenerator::pourLavafall(World& world, int gx, int gz, const NetherColumn& column) const { + int start = column.ceilingHeight - 1; + for (int y = start; y > params.lavaLevel; --y) { + if (world.blockAt(gx, y, gz) != Block::Air) break; + world.setBlock(gx, y, gz, Block::Lava); + } + if (world.blockAt(gx, start + 1, gz) == Block::Netherrack) + world.setBlock(gx, start + 1, gz, Block::Magma); +} + +void NetherGenerator::hangGlowstone(World& world, int gx, int gz, const NetherColumn& column, + uint32_t roll) const { + int drop = 1 + static_cast((roll >> 6) % 3u); + int spread = static_cast((roll >> 9) % 2u); + + for (int dx = -spread; dx <= spread; ++dx) { + for (int dz = -spread; dz <= spread; ++dz) { + int reach = drop - (std::abs(dx) + std::abs(dz)); + for (int step = 0; step < reach; ++step) { + int y = column.ceilingHeight - 1 - step; + if (world.blockAt(gx + dx, y, gz + dz) != Block::Air) break; + world.setBlock(gx + dx, y, gz + dz, Block::Glowstone); + } + } + } +} + +void NetherGenerator::plantFungus(World& world, int gx, int gz, const NetherColumn& column, + uint32_t roll) const { + int base = column.floorHeight + 1; + if (base <= params.lavaLevel) return; + if (world.blockAt(gx, base - 1, gz) != Block::Moss) return; + + int stem = 3 + static_cast((roll >> 12) % 5u); + int top = base + stem - 1; + if (top + 1 >= column.ceilingHeight) return; + + for (int y = base; y <= top; ++y) { + if (world.blockAt(gx, y, gz) != Block::Air) return; + world.setBlock(gx, y, gz, Block::Wood); + } + for (int dx = -1; dx <= 1; ++dx) { + for (int dz = -1; dz <= 1; ++dz) { + if (std::abs(dx) + std::abs(dz) > 1) continue; + if (world.blockAt(gx + dx, top + 1, gz + dz) == Block::Air) + world.setBlock(gx + dx, top + 1, gz + dz, Block::Leaves); + } + } +} + +void NetherGenerator::decorateColumn(World& world, int columnX, int columnZ) const { + int ox = columnX * chunkSize; + int oz = columnZ * chunkSize; + + for (int lx = 3; lx < chunkSize - 3; ++lx) { + for (int lz = 3; lz < chunkSize - 3; ++lz) { + int gx = ox + lx; + int gz = oz + lz; + NetherColumn column = columnAt(gx, gz); + uint32_t roll = mixCoord(params.seed ^ 0x4445434fu, gx, 0, gz); + + if (roll % 27u == 0u) hangGlowstone(world, gx, gz, column, roll); + + switch (column.biome) { + case NetherBiome::BasaltDeltas: + if ((roll >> 3) % 23u == 0u) raiseBasaltPillar(world, gx, gz, column, roll); + break; + case NetherBiome::CrimsonForest: + if ((roll >> 3) % 17u == 0u) plantFungus(world, gx, gz, column, roll); + break; + default: + break; + } + + if ((roll >> 7) % 97u == 0u) pourLavafall(world, gx, gz, column); + } + } +} + +} // namespace vf