From a9bf54ff8f39ef59a89fe957325bb3e04d4e45da Mon Sep 17 00:00:00 2001 From: Lord_Cambion Date: Fri, 24 Apr 2026 00:54:09 +0200 Subject: [PATCH] fix: mesa bryce now mesa bryce is implemented using decomp from ida 7 --- Minecraft.World/Biome.cpp | 2 +- Minecraft.World/MesaBiome.cpp | 477 +++++++++++++++---------- Minecraft.World/MesaBiome.h | 71 ++-- Minecraft.World/PerlinSimplexNoise.cpp | 2 +- 4 files changed, 334 insertions(+), 218 deletions(-) diff --git a/Minecraft.World/Biome.cpp b/Minecraft.World/Biome.cpp index 1d036950..ef58797a 100644 --- a/Minecraft.World/Biome.cpp +++ b/Minecraft.World/Biome.cpp @@ -148,7 +148,7 @@ void Biome::staticCtor() Biome::savannaM = (new MutatedSavannaBiome(163, biomes[35]))->setColor(0xe5da87)->setName(L"Savanna M")->setNoRain()->setTemperatureAndDownfall(1.1f, 0.0f)->setDepthAndScale(0.35f, 1.3f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Savanna, eMinecraftColour_Foliage_Savanna, eMinecraftColour_Sky_Desert, eMinecraftColour_Sky_Desert); Biome::savannaPlateauM = (new MutatedSavannaBiome(164, biomes[36]))->setColor(0xd1c890)->setName(L"Savanna Plateau M")->setNoRain()->setTemperatureAndDownfall(1.0f, 0.0f)->setDepthAndScale(1.05f, 1.2125f)->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Savanna, eMinecraftColour_Foliage_Savanna, eMinecraftColour_Sky_Desert, eMinecraftColour_Sky_Desert); - Biome::mesaBryce = (new MesaBiome(165, false, false))->setColor(0xd94515)->setName(L"Mesa (Bryce)")->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Mesa, eMinecraftColour_Foliage_Mesa, eMinecraftColour_Water_Mesa, eMinecraftColour_Sky_Desert); + Biome::mesaBryce = (new MesaBiome(165, true, false))->setColor(0xd94515)->setName(L"Mesa (Bryce)")->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Mesa, eMinecraftColour_Foliage_Mesa, eMinecraftColour_Water_Mesa, eMinecraftColour_Sky_Desert); Biome::mesaPlateauFM = (new MesaBiome(166, true, true))->setColor(0xb09765)->setName(L"Mesa Plateau F M")->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Mesa, eMinecraftColour_Foliage_Mesa, eMinecraftColour_Water_Mesa, eMinecraftColour_Sky_Desert); Biome::mesaPlateauM = (new MesaBiome(167, true, false))->setColor(0xca5936)->setName(L"Mesa Plateau M")->setLeafFoliageWaterSkyColor(eMinecraftColour_Grass_Mesa, eMinecraftColour_Foliage_Mesa, eMinecraftColour_Water_Mesa, eMinecraftColour_Sky_Desert); diff --git a/Minecraft.World/MesaBiome.cpp b/Minecraft.World/MesaBiome.cpp index 0572053e..1970db75 100644 --- a/Minecraft.World/MesaBiome.cpp +++ b/Minecraft.World/MesaBiome.cpp @@ -1,26 +1,23 @@ -#include "stdafx.h" - +#include "stdafx.h" #define _USE_MATH_DEFINES #include #include - #include "MesaBiome.h" -#include "BiomeDecorator.h" +#include "BiomeDecorator.h" #include "net.minecraft.world.level.h" #include "net.minecraft.world.level.tile.h" #include "ColoredTile.h" #include "SandTile.h" #include "DirtTile.h" #include "DyePowderItem.h" -#include "PerlinNoise.h" +#include "PerlinSimplexNoise.h" #include "Random.h" - +#include "TreeFeature.h" #undef max #undef min - MesaBiome::MesaBiome(int id, bool mesaPlateau, bool hasTrees) : Biome(id) { this->isMesaPlateau = mesaPlateau; @@ -29,31 +26,22 @@ MesaBiome::MesaBiome(int id, bool mesaPlateau, bool hasTrees) : Biome(id) this->setNoRain(); this->setTemperatureAndDownfall(2.0f, 0.0f); - // Red Sand (id=12, data=1) - // Orange Stained Hardened Clay (id=159, data=1) this->topMaterial = static_cast(Tile::sand_Id); - this->topMaterialData = static_cast(SandTile::RED_SAND); // 1 + this->topMaterialData = static_cast(SandTile::RED_SAND); this->material = static_cast(Tile::clayHardened_colored_Id); - this->materialData = static_cast(BAND_ORANGE); // 1 + this->materialData = static_cast(orangeColoredClayState); this->lastSeed = INVALID_SEED; + this->clayBands = nullptr; this->pillarNoise = nullptr; this->pillarRoofNoise = nullptr; this->clayBandsOffsetNoise = nullptr; - - /*friendlies.clear(); - friendlies_chicken.clear(); - enemies.clear(); - waterFriendlies.clear(); - ambientFriendlies.clear();*/ - - if (decorator) { - decorator->treeCount = hasTrees ? 5 : -999; + decorator->treeCount = hasTrees ? 5 : -999; decorator->deadBushCount = 20; - decorator->reedsCount = 3; + decorator->reedsCount = 3; decorator->cactusCount = 5; decorator->flowerCount = 0; } @@ -61,31 +49,135 @@ MesaBiome::MesaBiome(int id, bool mesaPlateau, bool hasTrees) : Biome(id) MesaBiome::~MesaBiome() { + delete[] clayBands; + clayBands = nullptr; + delete pillarNoise; + pillarNoise = nullptr; delete pillarRoofNoise; + pillarRoofNoise = nullptr; delete clayBandsOffsetNoise; + clayBandsOffsetNoise = nullptr; } - -void MesaBiome::initBands(int64_t /*seed*/) {} - - - - -int MesaBiome::getBandColor(int x, int y, int z) +void MesaBiome::generateBands(int64_t seed) { - if (!clayBandsOffsetNoise) - return BAND_HARDENED_CLAY; - double noiseX = static_cast(x) / 512.0; - int offset = static_cast(std::round( - clayBandsOffsetNoise->getValue(noiseX, noiseX) * 2.0)); + delete[] clayBands; + clayBands = new BandEntry[BAND_COUNT]; - int index = ((y + offset) % 64 + 64) % 64; - return static_cast(static_cast(clayBands[index])); + for (int i = 0; i < BAND_COUNT; ++i) + { + clayBands[i].blockId = Tile::clayHardened_Id; + clayBands[i].blockData = defaultHardenedClayState; + } + + Random r(seed); + + + delete clayBandsOffsetNoise; + clayBandsOffsetNoise = new PerlinSimplexNoise(&r, 1); + + { + int i = 0; + while (i < BAND_COUNT) + { + i += r.nextInt(5) + 1; + if (i < BAND_COUNT) + { + clayBands[i].blockId = Tile::clayHardened_colored_Id; + clayBands[i].blockData = orangeColoredClayState; + } + } + } + + { + int groupCount = r.nextInt(4) + 2; + for (int g = 0; g < groupCount; ++g) + { + int len = r.nextInt(3) + 1; + int start = r.nextInt(BAND_COUNT); + for (int k = 0; start + k < BAND_COUNT && k < len; ++k) + { + clayBands[start + k].blockId = Tile::clayHardened_colored_Id; + clayBands[start + k].blockData = yellowColoredClayState; + } + } + } + + { + int groupCount = r.nextInt(4) + 2; + for (int g = 0; g < groupCount; ++g) + { + int len = r.nextInt(3) + 2; + int start = r.nextInt(BAND_COUNT); + for (int k = 0; start + k < BAND_COUNT && k < len; ++k) + { + clayBands[start + k].blockId = Tile::clayHardened_colored_Id; + clayBands[start + k].blockData = brownColoredClayState; + } + } + } + + { + int groupCount = r.nextInt(4) + 2; + for (int g = 0; g < groupCount; ++g) + { + int len = r.nextInt(3) + 1; + int start = r.nextInt(BAND_COUNT); + for (int k = 0; start + k < BAND_COUNT && k < len; ++k) + { + clayBands[start + k].blockId = Tile::clayHardened_colored_Id; + clayBands[start + k].blockData = redColoredClayState; + } + } + } + + { + int stripeCount = r.nextInt(3) + 3; + int cursor = 0; + for (int g = 0; g < stripeCount; ++g) + { + cursor += r.nextInt(16) + 4; + if (cursor >= BAND_COUNT) break; + + clayBands[cursor].blockId = Tile::clayHardened_colored_Id; + clayBands[cursor].blockData = whiteColoredClayState; + + + if (cursor > 1 && r.nextBoolean()) + { + clayBands[cursor - 1].blockId = Tile::clayHardened_colored_Id; + clayBands[cursor - 1].blockData = silverColoredClayState; + } + + if (cursor < 63 && r.nextBoolean()) + { + clayBands[cursor + 1].blockId = Tile::clayHardened_colored_Id; + clayBands[cursor + 1].blockData = silverColoredClayState; + } + } + } } +BandEntry MesaBiome::getBand(int x, int y, int z) +{ + if (!clayBandsOffsetNoise || !clayBands) + return { Tile::clayHardened_Id, 0 }; + + + double noiseVal = clayBandsOffsetNoise->getValue( + static_cast(x) * 0.001953125, + static_cast(x) * 0.001953125); + + + int offset = static_cast(std::round(noiseVal + noiseVal)); + + + int index = ((y + offset) + BAND_COUNT) % BAND_COUNT; + return clayBands[index]; +} void MesaBiome::decorate(Level* level, Random* random, int xo, int zo) { @@ -94,203 +186,214 @@ void MesaBiome::decorate(Level* level, Random* random, int xo, int zo) Feature* MesaBiome::getTreeFeature(Random* random) { - return Biome::getTreeFeature(random); + return new TreeFeature(false); } +int MesaBiome::getFolageColor() const +{ + return eMinecraftColour_Foliage_Mesa; +} +int MesaBiome::getGrassColor() const +{ + return eMinecraftColour_Grass_Mesa; +} void MesaBiome::buildSurfaceAtDefault(Level* level, Random* random, byte* chunkBlocks, byte* chunkData, int x, int z, double noiseVal) { - int64_t seed = level->getSeed(); - if (lastSeed != seed) + + if (!clayBands || lastSeed != seed) + generateBands(seed); + + if (!pillarNoise || !pillarRoofNoise || lastSeed != seed) { - lastSeed = seed; - - - std::fill(std::begin(clayBands), std::end(clayBands), - static_cast(BAND_HARDENED_CLAY)); - { - Random r(seed); - delete clayBandsOffsetNoise; - clayBandsOffsetNoise = new PerlinNoise(&r, 1); - - // Orange sparse - for (int i = 0; i < 64; ) - { - i += r.nextInt(5) + 1; - if (i < 64) clayBands[i] = static_cast(BAND_ORANGE); - } - // Yellow groups - int yg = r.nextInt(4) + 2; - for (int g = 0; g < yg; ++g) { - int t = r.nextInt(3) + 1, s = r.nextInt(64); - for (int k = 0; s + k < 64 && k < t; ++k) - clayBands[s + k] = static_cast(BAND_YELLOW); - } - // Brown groups - int bg = r.nextInt(4) + 2; - for (int g = 0; g < bg; ++g) { - int t = r.nextInt(3) + 2, s = r.nextInt(64); - for (int k = 0; s + k < 64 && k < t; ++k) - clayBands[s + k] = static_cast(BAND_BROWN); - } - // Red groups - int rg = r.nextInt(4) + 2; - for (int g = 0; g < rg; ++g) { - int t = r.nextInt(3) + 1, s = r.nextInt(64); - for (int k = 0; s + k < 64 && k < t; ++k) - clayBands[s + k] = static_cast(BAND_RED); - } - // White stripes - int ws = r.nextInt(3) + 3, cursor = 0; - for (int g = 0; g < ws; ++g) { - cursor += r.nextInt(16) + 4; - if (cursor >= 64) break; - clayBands[cursor] = static_cast(BAND_WHITE); - if (cursor > 1 && r.nextBoolean()) clayBands[cursor - 1] = static_cast(BAND_SILVER); - if (cursor < 63 && r.nextBoolean()) clayBands[cursor + 1] = static_cast(BAND_SILVER); - } - } - + Random noiseRand(seed); + delete pillarNoise; + delete pillarRoofNoise; - delete pillarNoise; pillarNoise = nullptr; - delete pillarRoofNoise; pillarRoofNoise = nullptr; - { - Random r(seed); - pillarNoise = new PerlinNoise(&r, 4); // field_150623_aE - pillarRoofNoise = new PerlinNoise(&r, 1); // field_150624_aF - } + pillarNoise = new PerlinSimplexNoise(&noiseRand, 4); + pillarRoofNoise = new PerlinSimplexNoise(&noiseRand, 1); } - - const int seaLevel = level->seaLevel; - const int localX = x & 15; - const int localZ = z & 15; + lastSeed = seed; - - int noiseDepth = (int)(noiseVal / 3.0 + 3.0 + random->nextDouble() * 0.25); - bool flag = (cos(noiseVal / 3.0 * PI) > 0.0); + const int localX = x & 0xF; + const int localZ = z & 0xF; - int run = -1; - bool flag1 = false; + double pillarHeight = 0.0; - for (int y = Level::genDepthMinusOne; y >= 0; --y) + + if (isMesaPlateau) +{ + double nx = static_cast((x & ~0xF) + localZ); + double nz = static_cast((z & ~0xF) + localX); + + + double roofVal = pillarNoise->getValue(nx * 0.25, nz * 0.25); + double d0 = std::abs(noiseVal) - roofVal; + + + if (d0 > 0.0) { - int index = (localZ * 16 + localX) * Level::genDepth + y; + + double pillarScale = pillarRoofNoise->getValue( + nx * 0.001953125, + nz * 0.001953125); - if (y <= 1 + random->nextInt(2)) + double scaled = std::ceil(std::abs(pillarScale) * 50.0); + double height = d0 * d0 * 2.5; + double cap = scaled + 14.0; + if (height > cap) height = cap; + pillarHeight = height + 64.0; + } +} + + const int localX2 = x & 0xF; + const int localZ2 = z & 0xF; + const int seaLevel = level->getSeaLevel(); + + int noiseDepth = static_cast(noiseVal / 3.0 + 3.0 + random->nextDouble() * 0.25); + bool cosFlag = (std::cos(noiseVal / 3.0 * PI) > 0.0); + + int run = -1; + bool underRedSand = false; + + for (int y = 0x7F; y >= 0; --y) + { + int idx = (localZ2 * 16 + localX2) * 128 + y; + + + byte cur = chunkBlocks[idx]; + if (cur == 0 && pillarHeight > 0.0 && y < static_cast(pillarHeight)) { - chunkBlocks[index] = static_cast(Tile::unbreakable_Id); + chunkBlocks[idx] = static_cast(Tile::stone_Id); + cur = static_cast(Tile::stone_Id); + } + + + if (y <= random->nextInt(5)) + { + chunkBlocks[idx] = static_cast(Tile::unbreakable_Id); continue; } - byte cur = chunkBlocks[index]; + + cur = chunkBlocks[idx]; - if (cur == 0) + + if (cur == 0) { run = -1; + continue; } - else if (cur == static_cast(Tile::stone_Id)) + + + if (cur != static_cast(Tile::stone_Id)) + continue; + + if (run == -1) { - if (run == -1) + underRedSand = false; + run = noiseDepth + std::max(0, y - seaLevel); + + + if (y < seaLevel - 1) { - flag1 = false; - - - run = noiseDepth + (y > seaLevel ? (y - seaLevel) : 0); - - - if (y < seaLevel - 1) + if (noiseDepth <= 0) { - if (noiseDepth <= 0) - { - chunkBlocks[index] = static_cast(Tile::stone_Id); - } - else - { - chunkBlocks[index] = static_cast(Tile::clayHardened_colored_Id); - chunkData[index] = static_cast(BAND_ORANGE); - } - } - else if (hasTrees && y > 86 + noiseDepth * 2) - { - if (flag) - { - chunkBlocks[index] = static_cast(Tile::grass_Id); - } - else - { - chunkBlocks[index] = static_cast(Tile::dirt_Id); - chunkData[index] = static_cast(DirtTile::COARSE_DIRT); - } - } - else if (y <= seaLevel + 3 + noiseDepth) - { - chunkBlocks[index] = static_cast(Tile::sand_Id); - chunkData[index] = static_cast(SandTile::RED_SAND); // 1 - flag1 = true; + chunkBlocks[idx] = static_cast(Tile::stone_Id); } else { - if (y >= 64) - { - if (flag) - { - chunkBlocks[index] = static_cast(Tile::clayHardened_Id); - } - else - { - int band = getBandColor(x, y, z); - if (band == BAND_HARDENED_CLAY) - { - chunkBlocks[index] = static_cast(Tile::clayHardened_Id); - } - else - { - chunkBlocks[index] = static_cast(Tile::clayHardened_colored_Id); - chunkData[index] = static_cast(band); - } - } - } - else - { - chunkBlocks[index] = static_cast(Tile::clayHardened_colored_Id); - chunkData[index] = static_cast(BAND_ORANGE); - } - } - - if (y < seaLevel && chunkBlocks[index] == 0) - { - chunkBlocks[index] = (getTemperature(x, y, z) < 0.15f) - ? static_cast(Tile::ice_Id) - : static_cast(Tile::calmWater_Id); + chunkBlocks[idx] = static_cast(Tile::clayHardened_colored_Id); + chunkData[idx] = static_cast(BAND_ORANGE); } } - else if (run > 0) + else if (hasTrees && y > 86 + noiseDepth * 2) { - --run; - - if (flag1) + + if (cosFlag) { - chunkBlocks[index] = static_cast(Tile::clayHardened_colored_Id); - chunkData[index] = static_cast(BAND_ORANGE); + chunkBlocks[idx] = static_cast(Tile::dirt_Id); + chunkData[idx] = static_cast(DirtTile::COARSE_DIRT); } else { - int band = getBandColor(x, y, z); - if (band == BAND_HARDENED_CLAY) - chunkBlocks[index] = static_cast(Tile::clayHardened_Id); + chunkBlocks[idx] = static_cast(Tile::grass_Id); + } + } + else if (y <= seaLevel + 3 + noiseDepth) + { + chunkBlocks[idx] = static_cast(Tile::sand_Id); + chunkData[idx] = static_cast(SandTile::RED_SAND); + underRedSand = true; + } + else + { + + if (y >= 64 && y <= 127) + { + if (cosFlag) + { + chunkBlocks[idx] = static_cast(Tile::clayHardened_Id); + } else { - chunkBlocks[index] = static_cast(Tile::clayHardened_colored_Id); - chunkData[index] = static_cast(band); + BandEntry band = getBand(x, y, z); + chunkBlocks[idx] = static_cast(band.blockId); + if (band.blockId == Tile::clayHardened_colored_Id) + chunkData[idx] = static_cast(band.blockData); } } + else + { + chunkBlocks[idx] = static_cast(Tile::clayHardened_colored_Id); + chunkData[idx] = static_cast(BAND_ORANGE); + } + } + + + if (y < seaLevel && chunkBlocks[idx] == 0) + chunkBlocks[idx] = static_cast(Tile::calmWater_Id); + } + else if (run > 0) + { + --run; + + if (underRedSand) + { + chunkBlocks[idx] = static_cast(Tile::clayHardened_colored_Id); + chunkData[idx] = static_cast(BAND_ORANGE); + } + else + { + BandEntry band = getBand(x, y, z); + chunkBlocks[idx] = static_cast(band.blockId); + if (band.blockId == Tile::clayHardened_colored_Id) + chunkData[idx] = static_cast(band.blockData); } } } } + +MesaBiome* MesaBiome::createMutatedCopy(int newId) +{ + + bool isMesaBase = (this->id == Biome::mesa->id); + + MesaBiome* copy = new MesaBiome(newId, isMesaBase, this->hasTrees); + + if (!isMesaBase) + { + + copy->setDepthAndScale(0.1f, 0.3f); + } + + copy->setWaterSkyColor(this->getWaterColor(), this->getSkyColor()); + + return copy; +} \ No newline at end of file diff --git a/Minecraft.World/MesaBiome.h b/Minecraft.World/MesaBiome.h index 991904ba..d0df393d 100644 --- a/Minecraft.World/MesaBiome.h +++ b/Minecraft.World/MesaBiome.h @@ -1,49 +1,62 @@ #pragma once #include "Biome.h" -#include "PerlinNoise.h" +#include "PerlinSimplexNoise.h" #include "Random.h" -#include "Level.h" -#include "Feature.h" +#include "Level.h" +#include "Feature.h" #include +struct BandEntry { + int blockId; + int blockData; +}; + class MesaBiome : public Biome { public: - - static constexpr int BAND_HARDENED_CLAY = 255; - static constexpr int BAND_WHITE = 0; - static constexpr int BAND_ORANGE = 1; - static constexpr int BAND_YELLOW = 4; + static constexpr int BAND_COUNT = 64; + + static constexpr int BAND_WHITE = 0; + static constexpr int BAND_ORANGE = 1; + static constexpr int BAND_YELLOW = 4; static constexpr int BAND_BROWN = 12; static constexpr int BAND_RED = 14; - static constexpr int BAND_SILVER = 8; + static constexpr int BAND_SILVER = 8; - static constexpr int64_t INVALID_SEED = -1LL; + static constexpr int defaultHardenedClayState = 0; + static constexpr int orangeColoredClayState = BAND_ORANGE; + static constexpr int yellowColoredClayState = BAND_YELLOW; + static constexpr int brownColoredClayState = BAND_BROWN; + static constexpr int redColoredClayState = BAND_RED; + static constexpr int whiteColoredClayState = BAND_WHITE; + static constexpr int silverColoredClayState = BAND_SILVER; - MesaBiome(int id, bool mesaPlateau, bool hasTrees); + static constexpr int64_t INVALID_SEED = 0LL; + + MesaBiome(int id, bool isMesaPlateau, bool hasTrees); virtual ~MesaBiome(); - virtual void decorate(Level* level, Random* random, - int xo, int zo) override; - virtual Feature* getTreeFeature(Random* random) override; - virtual void buildSurfaceAtDefault(Level* level, Random* random, - byte* chunkBlocks, byte* chunkData, - int x, int z, double noiseVal) override; + virtual void decorate(Level* level, Random* random, int xo, int zo) override; + virtual Feature* getTreeFeature(Random* random) override; + virtual void buildSurfaceAtDefault(Level* level, Random* random, + byte* chunkBlocks, byte* chunkData, + int x, int z, double noiseVal) override; + virtual int getFolageColor() const override; + virtual int getGrassColor() const override; + + MesaBiome* createMutatedCopy(int newId); private: - - void initBands(int64_t seed); + void generateBands(int64_t seed); + BandEntry getBand(int x, int y, int z); - int getBandColor(int x, int y, int z); + bool isMesaPlateau; //0x104 + bool hasTrees; //0x105 - bool isMesaPlateau; - bool hasTrees; + int64_t lastSeed; //0xF0/0xF4 - int64_t lastSeed; - - byte clayBands[64]; - - PerlinNoise* clayBandsOffsetNoise; - PerlinNoise* pillarNoise; - PerlinNoise* pillarRoofNoise; + BandEntry* clayBands; //0xE8 + PerlinSimplexNoise* pillarNoise; //0xF8 + PerlinSimplexNoise* pillarRoofNoise; //0xFC + PerlinSimplexNoise* clayBandsOffsetNoise; //0x100 }; \ No newline at end of file diff --git a/Minecraft.World/PerlinSimplexNoise.cpp b/Minecraft.World/PerlinSimplexNoise.cpp index 97d11448..7f620cf5 100644 --- a/Minecraft.World/PerlinSimplexNoise.cpp +++ b/Minecraft.World/PerlinSimplexNoise.cpp @@ -10,7 +10,7 @@ PerlinSimplexNoise::PerlinSimplexNoise(int levels) PerlinSimplexNoise::PerlinSimplexNoise(Random *random, int levels) { init(random,levels); - delete random; + //delete random; } void PerlinSimplexNoise::init(Random *random, int levels)