From 41d4334e80318c689e69fa2e07aaa071f5efa9db Mon Sep 17 00:00:00 2001 From: Lord_Cambion Date: Sun, 26 Apr 2026 16:12:20 +0200 Subject: [PATCH] fix: savanna biome + savanna tree used compilation to change savanna biome generation and savanna tree teatures using abstractTreeFeature that was missing. --- Minecraft.World/AbstractTreeFeature.h | 33 ++++ Minecraft.World/Direction.h | 20 +- Minecraft.World/SavannaBiome.cpp | 22 +-- Minecraft.World/SavannaBiome.h | 7 +- Minecraft.World/SavannaTreeFeature.cpp | 244 ++++++++++++++++--------- Minecraft.World/SavannaTreeFeature.h | 26 +-- 6 files changed, 230 insertions(+), 122 deletions(-) create mode 100644 Minecraft.World/AbstractTreeFeature.h diff --git a/Minecraft.World/AbstractTreeFeature.h b/Minecraft.World/AbstractTreeFeature.h new file mode 100644 index 00000000..37703e55 --- /dev/null +++ b/Minecraft.World/AbstractTreeFeature.h @@ -0,0 +1,33 @@ +#pragma once +#include "Feature.h" +#include "Level.h" +#include "Tile.h" + +class AbstractTreeFeature : public Feature +{ +public: + AbstractTreeFeature(bool doUpdate) : Feature(doUpdate) {} + virtual ~AbstractTreeFeature() {} + + static bool isFree(Level* level, int x, int y, int z) + { + int tile = level->getTile(x, y, z); + return tile == 0 + || tile == Tile::leaves_Id + || tile == Tile::leaves2_Id + || tile == Tile::treeTrunk_Id + || tile == Tile::tree2Trunk_Id + || tile == Tile::vine_Id + || tile == Tile::tallgrass_Id + || tile == Tile::flower_Id; + } + + void setDirtAt(Level* level, int x, int y, int z) + { + if (level->getTile(x, y, z) != Tile::dirt_Id) + { + placeBlock(level, x, y, z, Tile::dirt_Id, 0); + } + } + virtual void postPlaceTree() {} +}; \ No newline at end of file diff --git a/Minecraft.World/Direction.h b/Minecraft.World/Direction.h index 587bb653..8b8b91bf 100644 --- a/Minecraft.World/Direction.h +++ b/Minecraft.World/Direction.h @@ -54,4 +54,22 @@ public: return 0; } -}; \ No newline at end of file + + class Plane + { + public: + + static int getRandomFace(Random* random) + { + + static const int horizontal[4] = { + Direction::SOUTH, + Direction::WEST, + Direction::NORTH, + Direction::EAST + }; + return horizontal[random->nextInt(4)]; + } + }; + +}; diff --git a/Minecraft.World/SavannaBiome.cpp b/Minecraft.World/SavannaBiome.cpp index 37122a41..3181b63d 100644 --- a/Minecraft.World/SavannaBiome.cpp +++ b/Minecraft.World/SavannaBiome.cpp @@ -22,11 +22,11 @@ SavannaBiome::SavannaBiome(int id) : Biome(id) Feature* SavannaBiome::getTreeFeature(Random* random) { - if (random->nextInt(5) <= 0) + if (random->nextInt(5) > 0) { - return new TreeFeature(false); + return new SavannaTreeFeature(false); } - return new SavannaTreeFeature(false); + return new TreeFeature(false); } int SavannaBiome::getGrassColor() const @@ -86,11 +86,11 @@ MutatedSavannaBiome::MutatedSavannaBiome(int id, Biome* baseBiome) decorator->grassCount = 5; } -void MutatedSavannaBiome::buildSurfaceAtDefault(Level* level, Random* random, - byte* chunkBlocks, - int x, int z, double noiseVal) +void MutatedSavannaBiome::buildSurfaceAt(Level* level, Random* random, + ChunkPrimer* primer, + int x, int z, double noiseVal) { - + topMaterial = static_cast(Tile::grass_Id); topMaterialData = 0; material = static_cast(Tile::dirt_Id); @@ -98,7 +98,7 @@ void MutatedSavannaBiome::buildSurfaceAtDefault(Level* level, Random* random, if (noiseVal > 1.75) { - + topMaterial = static_cast(Tile::stone_Id); topMaterialData = 0; material = static_cast(Tile::stone_Id); @@ -108,13 +108,13 @@ void MutatedSavannaBiome::buildSurfaceAtDefault(Level* level, Random* random, { topMaterial = static_cast(Tile::dirt_Id); - topMaterialData = 1; + topMaterialData = 1; material = static_cast(Tile::dirt_Id); materialData = 0; } - - Biome::buildSurfaceAtDefault(level, random, chunkBlocks, x, z, noiseVal); + + Biome::buildSurfaceAt(level, random, primer, x, z, noiseVal); } void MutatedSavannaBiome::decorate(Level* level, Random* random, int xo, int zo) diff --git a/Minecraft.World/SavannaBiome.h b/Minecraft.World/SavannaBiome.h index 66c21310..f942a651 100644 --- a/Minecraft.World/SavannaBiome.h +++ b/Minecraft.World/SavannaBiome.h @@ -16,12 +16,13 @@ public: virtual Biome* createMutatedCopy(int newId); }; + class MutatedSavannaBiome : public MutatedBiome { public: MutatedSavannaBiome(int id, Biome* baseBiome); - virtual void buildSurfaceAtDefault(Level* level, Random* random, - byte* chunkBlocks, int x, int z, - double noiseVal) override; + virtual void buildSurfaceAt(Level* level, Random* random, + ChunkPrimer* primer, int x, int z, + double noiseVal) override; virtual void decorate(Level* level, Random* random, int xo, int zo) override; }; \ No newline at end of file diff --git a/Minecraft.World/SavannaTreeFeature.cpp b/Minecraft.World/SavannaTreeFeature.cpp index 39ac2c28..48457f21 100644 --- a/Minecraft.World/SavannaTreeFeature.cpp +++ b/Minecraft.World/SavannaTreeFeature.cpp @@ -1,122 +1,188 @@ #include "stdafx.h" #include "SavannaTreeFeature.h" #include "net.minecraft.world.level.tile.h" -#include "TreeTile2.h" -#include "LeafTile2.h" #include "Level.h" +#include "Random.h" +#include "Direction.h" -SavannaTreeFeature::SavannaTreeFeature(bool doUpdate) : Feature(doUpdate) { - this->baseHeight = 5; +SavannaTreeFeature::SavannaTreeFeature(bool doUpdate) : AbstractTreeFeature(doUpdate) +{ } -bool SavannaTreeFeature::place(Level* level, Random* random, int x, int y, int z) { - int height = random->nextInt(3) + baseHeight; - int ground = level->getTile(x, y - 1, z); - if (ground != Tile::grass_Id && ground != Tile::dirt_Id) return false; - - - if (random->nextBoolean()) { - generateForkingTree(level, random, x, y, z, height); - } else { - generateBendingTree(level, random, x, y, z, height); - } - - return true; +void SavannaTreeFeature::placeLog(Level* level, int x, int y, int z) +{ + placeBlock(level, x, y, z, Tile::tree2Trunk_Id, 0); } - -void SavannaTreeFeature::generateForkingTree(Level* level, Random* random, int x, int y, int z, int height) { - int curX = x; - int curZ = z; - int forkH = height - random->nextInt(4) - 1; - - - int dx1 = random->nextInt(3) - 1; - int dz1 = (dx1 == 0) ? (random->nextBoolean() ? 1 : -1) : (random->nextInt(3) - 1); - - for (int h = 0; h < height; h++) { - if (h >= forkH) { curX += dx1; curZ += dz1; } - placeBlock(level, curX, y + h, curZ, Tile::tree2Trunk_Id, TreeTile2::ACACIA_TRUNK); - if (h == height - 1) generateLeafCap(level, curX, y + h, curZ); +void SavannaTreeFeature::placeLeafAt(Level* level, int x, int y, int z) +{ + int tile = level->getTile(x, y, z); + if (tile == 0 || tile == Tile::leaves_Id || tile == Tile::leaves2_Id) + { + placeBlock(level, x, y, z, Tile::leaves2_Id, 0); } +} - - int dx2 = random->nextInt(3) - 1; - int dz2 = random->nextInt(3) - 1; - if (dx2 != dx1 || dz2 != dz1) { - int curX2 = x; - int curZ2 = z; - int forkH2 = forkH - random->nextInt(2) - 1; - for (int h = forkH2; h < height; h++) { - if (h >= 1) { - curX2 += dx2; curZ2 += dz2; - placeBlock(level, curX2, y + h, curZ2, Tile::tree2Trunk_Id, TreeTile2::ACACIA_TRUNK); - if (h == height - 1) generateLeafCap(level, curX2, y + h, curZ2); +void SavannaTreeFeature::placeLeavesLayer3(Level* level, int cx, int cy, int cz) +{ + for (int dx = -3; dx <= 3; ++dx) + { + for (int dz = -3; dz <= 3; ++dz) + { + if (abs(dx) != 3 || abs(dz) != 3) + { + placeLeafAt(level, cx + dx, cy, cz + dz); } } } } +void SavannaTreeFeature::placeLeavesLayer1(Level* level, int cx, int cy, int cz) +{ + for (int dx = -1; dx <= 1; ++dx) + { + for (int dz = -1; dz <= 1; ++dz) + { + placeLeafAt(level, cx + dx, cy, cz + dz); + } + } + placeLeafAt(level, cx + 2, cy, cz); + placeLeafAt(level, cx - 2, cy, cz); + placeLeafAt(level, cx, cy, cz + 2); + placeLeafAt(level, cx, cy, cz - 2); +} + +bool SavannaTreeFeature::place(Level* level, Random* random, int x, int y, int z) +{ + + int height = random->nextInt(3) + random->nextInt(3) + 5; + + if (y <= 0 || y + height + 1 > 256) + return false; + + bool canPlace = true; + for (int j = y; j <= y + 1 + height && canPlace; ++j) + { + int radius = 1; + if (j == y) radius = 0; + if (j >= y + 1 + height - 2) radius = 2; + + for (int lx = x - radius; lx <= x + radius && canPlace; ++lx) + { + for (int lz = z - radius; lz <= z + radius && canPlace; ++lz) + { + if (j >= 0 && j < 256) + { + if (!AbstractTreeFeature::isFree(level, lx, j, lz)) + canPlace = false; + } + else + { + canPlace = false; + } + } + } + } + + if (!canPlace) + return false; + + int belowTile = level->getTile(x, y - 1, z); + if (belowTile != Tile::grass_Id && belowTile != Tile::dirt_Id) + return false; + + if (y >= 255 - height) + return false; + + setDirtAt(level, x, y - 1, z); -void SavannaTreeFeature::generateBendingTree(Level* level, Random* random, int x, int y, int z, int height) { + int facing1 = Direction::Plane::getRandomFace(random); + int branchStart = height - random->nextInt(4) - 1; + int branchLen = 3 - random->nextInt(3); + int curX = x; int curZ = z; - int curY = y; + int topY = y; - - int dirX = 0, dirZ = 0; - int roll = random->nextInt(4); - if (roll == 0) dirX = 1; else if (roll == 1) dirX = -1; else if (roll == 2) dirZ = 1; else dirZ = -1; + for (int l1 = 0; l1 < height; ++l1) + { + int curY = y + l1; - - int straightHeight = 2 + random->nextInt(3); - for (int i = 0; i < straightHeight; i++) { - placeBlock(level, curX, curY, curZ, Tile::tree2Trunk_Id, TreeTile2::ACACIA_TRUNK); - curY++; - } + if (l1 >= branchStart && branchLen > 0) + { + curX += Direction::getStepX(facing1); + curZ += Direction::getStepZ(facing1); + --branchLen; + } - - int diagonalSteps = 2 + random->nextInt(2); - for (int i = 0; i < diagonalSteps; i++) { - curX += dirX; - curZ += dirZ; - - placeBlock(level, curX, curY, curZ, Tile::tree2Trunk_Id, TreeTile2::ACACIA_TRUNK); - - - if (i < diagonalSteps - 1) { - curY++; + int tile = level->getTile(curX, curY, curZ); + if (tile == 0 || tile == Tile::leaves_Id || tile == Tile::leaves2_Id) + { + placeLog(level, curX, curY, curZ); + topY = curY; } } - - generateLeafCap(level, curX, curY, curZ); -} + + placeLeavesLayer3(level, curX, topY, curZ); + placeLeavesLayer1(level, curX, topY + 1, curZ); -void SavannaTreeFeature::generateLeafCap(Level* level, int x, int y, int z) { - - for (int lx = -3; lx <= 3; lx++) { - for (int lz = -3; lz <= 3; lz++) { + int curX2 = x; + int curZ2 = z; + int facing2 = Direction::Plane::getRandomFace(random); + + if (facing2 != facing1) + { + + int start2 = branchStart - random->nextInt(2) - 1; + int steps2 = 1 + random->nextInt(3); + int topY2 = 0; + + + for (int l4 = start2; l4 < height && steps2 > 0; --steps2) + { + if (l4 >= 1) + { + int curY2 = y + l4; + curX2 += Direction::getStepX(facing2); + curZ2 += Direction::getStepZ(facing2); + + int tile2 = level->getTile(curX2, curY2, curZ2); + if (tile2 == 0 || tile2 == Tile::leaves_Id || tile2 == Tile::leaves2_Id) + { + placeLog(level, curX2, curY2, curZ2); + topY2 = curY2; + } + } + ++l4; + } + + + if (topY2 > 0) + { - if (abs(lx) == 3 && abs(lz) == 3) continue; - if (abs(lx) + abs(lz) > 4) continue; - placeLeaf(level, x + lx, y, z + lz); + for (int dx = -2; dx <= 2; ++dx) + { + for (int dz = -2; dz <= 2; ++dz) + { + if (abs(dx) != 2 || abs(dz) != 2) + { + placeLeafAt(level, curX2 + dx, topY2, curZ2 + dz); + } + } + } + + for (int dx = -1; dx <= 1; ++dx) + { + for (int dz = -1; dz <= 1; ++dz) + { + placeLeafAt(level, curX2 + dx, topY2 + 1, curZ2 + dz); + } + } } } - - for (int lx = -2; lx <= 2; lx++) { - for (int lz = -2; lz <= 2; lz++) { - if (abs(lx) == 2 && abs(lz) == 2) continue; - placeLeaf(level, x + lx, y + 1, z + lz); - } - } -} - -void SavannaTreeFeature::placeLeaf(Level* level, int x, int y, int z) { - if (level->getTile(x, y, z) == 0) { - placeBlock(level, x, y, z, Tile::leaves2_Id, 0); - } + return true; } \ No newline at end of file diff --git a/Minecraft.World/SavannaTreeFeature.h b/Minecraft.World/SavannaTreeFeature.h index 7c263178..83e04dc6 100644 --- a/Minecraft.World/SavannaTreeFeature.h +++ b/Minecraft.World/SavannaTreeFeature.h @@ -1,28 +1,18 @@ #pragma once -#include "net.minecraft.world.level.levelgen.feature.h" -#include "Feature.h" +#include "AbstractTreeFeature.h" -class SavannaTreeFeature : public Feature +class SavannaTreeFeature : public AbstractTreeFeature { public: - SavannaTreeFeature(bool doUpdate); - - virtual bool place(Level* level, Random* random, int x, int y, int z) override; private: - int baseHeight; + static int s_logState; + static int s_leafState; - - void generateBendingTree(Level* level, Random* random, int x, int y, int z, int height); - - - void generateForkingTree(Level* level, Random* random, int x, int y, int z, int height); - - - void generateLeafCap(Level* level, int x, int y, int z); - - - void placeLeaf(Level* level, int x, int y, int z); + void placeLog(Level* level, int x, int y, int z); + void placeLeafAt(Level* level, int x, int y, int z); + void placeLeavesLayer3(Level* level, int cx, int cy, int cz); + void placeLeavesLayer1(Level* level, int cx, int cy, int cz); }; \ No newline at end of file