fix: mesa bryce

now mesa bryce is implemented using decomp from ida 7
This commit is contained in:
Lord_Cambion 2026-04-24 00:54:09 +02:00
parent 4303b4966a
commit a9bf54ff8f
4 changed files with 334 additions and 218 deletions

View file

@ -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);

View file

@ -1,26 +1,23 @@
#include "stdafx.h"
#include "stdafx.h"
#define _USE_MATH_DEFINES
#include <cmath>
#include <algorithm>
#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<byte>(Tile::sand_Id);
this->topMaterialData = static_cast<byte>(SandTile::RED_SAND); // 1
this->topMaterialData = static_cast<byte>(SandTile::RED_SAND);
this->material = static_cast<byte>(Tile::clayHardened_colored_Id);
this->materialData = static_cast<byte>(BAND_ORANGE); // 1
this->materialData = static_cast<byte>(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<double>(x) / 512.0;
int offset = static_cast<int>(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<int>(static_cast<unsigned char>(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<double>(x) * 0.001953125,
static_cast<double>(x) * 0.001953125);
int offset = static_cast<int>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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<byte>(BAND_WHITE);
if (cursor > 1 && r.nextBoolean()) clayBands[cursor - 1] = static_cast<byte>(BAND_SILVER);
if (cursor < 63 && r.nextBoolean()) clayBands[cursor + 1] = static_cast<byte>(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<double>((x & ~0xF) + localZ);
double nz = static_cast<double>((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<int>(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<int>(pillarHeight))
{
chunkBlocks[index] = static_cast<byte>(Tile::unbreakable_Id);
chunkBlocks[idx] = static_cast<byte>(Tile::stone_Id);
cur = static_cast<byte>(Tile::stone_Id);
}
if (y <= random->nextInt(5))
{
chunkBlocks[idx] = static_cast<byte>(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<byte>(Tile::stone_Id))
if (cur != static_cast<byte>(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<byte>(Tile::stone_Id);
}
else
{
chunkBlocks[index] = static_cast<byte>(Tile::clayHardened_colored_Id);
chunkData[index] = static_cast<byte>(BAND_ORANGE);
}
}
else if (hasTrees && y > 86 + noiseDepth * 2)
{
if (flag)
{
chunkBlocks[index] = static_cast<byte>(Tile::grass_Id);
}
else
{
chunkBlocks[index] = static_cast<byte>(Tile::dirt_Id);
chunkData[index] = static_cast<byte>(DirtTile::COARSE_DIRT);
}
}
else if (y <= seaLevel + 3 + noiseDepth)
{
chunkBlocks[index] = static_cast<byte>(Tile::sand_Id);
chunkData[index] = static_cast<byte>(SandTile::RED_SAND); // 1
flag1 = true;
chunkBlocks[idx] = static_cast<byte>(Tile::stone_Id);
}
else
{
if (y >= 64)
{
if (flag)
{
chunkBlocks[index] = static_cast<byte>(Tile::clayHardened_Id);
}
else
{
int band = getBandColor(x, y, z);
if (band == BAND_HARDENED_CLAY)
{
chunkBlocks[index] = static_cast<byte>(Tile::clayHardened_Id);
}
else
{
chunkBlocks[index] = static_cast<byte>(Tile::clayHardened_colored_Id);
chunkData[index] = static_cast<byte>(band);
}
}
}
else
{
chunkBlocks[index] = static_cast<byte>(Tile::clayHardened_colored_Id);
chunkData[index] = static_cast<byte>(BAND_ORANGE);
}
}
if (y < seaLevel && chunkBlocks[index] == 0)
{
chunkBlocks[index] = (getTemperature(x, y, z) < 0.15f)
? static_cast<byte>(Tile::ice_Id)
: static_cast<byte>(Tile::calmWater_Id);
chunkBlocks[idx] = static_cast<byte>(Tile::clayHardened_colored_Id);
chunkData[idx] = static_cast<byte>(BAND_ORANGE);
}
}
else if (run > 0)
else if (hasTrees && y > 86 + noiseDepth * 2)
{
--run;
if (flag1)
if (cosFlag)
{
chunkBlocks[index] = static_cast<byte>(Tile::clayHardened_colored_Id);
chunkData[index] = static_cast<byte>(BAND_ORANGE);
chunkBlocks[idx] = static_cast<byte>(Tile::dirt_Id);
chunkData[idx] = static_cast<byte>(DirtTile::COARSE_DIRT);
}
else
{
int band = getBandColor(x, y, z);
if (band == BAND_HARDENED_CLAY)
chunkBlocks[index] = static_cast<byte>(Tile::clayHardened_Id);
chunkBlocks[idx] = static_cast<byte>(Tile::grass_Id);
}
}
else if (y <= seaLevel + 3 + noiseDepth)
{
chunkBlocks[idx] = static_cast<byte>(Tile::sand_Id);
chunkData[idx] = static_cast<byte>(SandTile::RED_SAND);
underRedSand = true;
}
else
{
if (y >= 64 && y <= 127)
{
if (cosFlag)
{
chunkBlocks[idx] = static_cast<byte>(Tile::clayHardened_Id);
}
else
{
chunkBlocks[index] = static_cast<byte>(Tile::clayHardened_colored_Id);
chunkData[index] = static_cast<byte>(band);
BandEntry band = getBand(x, y, z);
chunkBlocks[idx] = static_cast<byte>(band.blockId);
if (band.blockId == Tile::clayHardened_colored_Id)
chunkData[idx] = static_cast<byte>(band.blockData);
}
}
else
{
chunkBlocks[idx] = static_cast<byte>(Tile::clayHardened_colored_Id);
chunkData[idx] = static_cast<byte>(BAND_ORANGE);
}
}
if (y < seaLevel && chunkBlocks[idx] == 0)
chunkBlocks[idx] = static_cast<byte>(Tile::calmWater_Id);
}
else if (run > 0)
{
--run;
if (underRedSand)
{
chunkBlocks[idx] = static_cast<byte>(Tile::clayHardened_colored_Id);
chunkData[idx] = static_cast<byte>(BAND_ORANGE);
}
else
{
BandEntry band = getBand(x, y, z);
chunkBlocks[idx] = static_cast<byte>(band.blockId);
if (band.blockId == Tile::clayHardened_colored_Id)
chunkData[idx] = static_cast<byte>(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;
}

View file

@ -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 <cstdint>
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
};

View file

@ -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)