diff --git a/Minecraft.World/Layer.cpp b/Minecraft.World/Layer.cpp index 35149330..bfa84f00 100644 --- a/Minecraft.World/Layer.cpp +++ b/Minecraft.World/Layer.cpp @@ -165,14 +165,11 @@ Layer::Layer(int64_t s) void Layer::initRandom(int64_t x, int64_t y) { - static bool first = true; - - int64_t xi = (int64_t)(int32_t)x; int64_t yi = (int64_t)(int32_t)y; int64_t v4 = (0x5851F42D4C957F2DLL * seed + 0x14057B7EF767814FLL) * seed + xi; - uint32_t v5 = 1284865837u * (uint32_t)(v4 * (1284865837LL * (int32_t)v4 - 144211633LL) + yi) - 144211633u; + uint32_t v5 = 1284865837u * (uint32_t)(v4 * (1284865837LL * v4 - 144211633LL) + yi) - 144211633u; int64_t paired = (int64_t)(((uint64_t)v5 << 32) | (uint64_t)v5); int64_t v6 = paired * (v4 * (0x5851F42D4C957F2DLL * v4 + 0x14057B7EF767814FLL) + yi) + xi; uint32_t lo = 1284865837u * (uint32_t)v6 - 144211633u; @@ -186,19 +183,19 @@ int Layer::nextRandom(int max) { int64_t rval_full = this->rval; uint32_t rval_lo = (uint32_t)rval_full; - uint32_t rval_hi = (uint32_t)(rval_full >> 32); uint32_t seed_lo = (uint32_t)this->seed; + uint32_t seed_hi = (uint32_t)(this->seed >> 32); int result = (int)((int64_t)(rval_full >> 24) % (int64_t)max); if (result < 0) result += max; - uint32_t new_lo = rval_lo * (1284865837u * rval_lo - 144211633u) + seed_lo; + uint32_t v9 = rval_lo * (1284865837u * rval_lo - 144211633u); + uint32_t new_lo = v9 + seed_lo; - uint64_t paired = ((uint64_t)rval_lo << 32) | (uint64_t)rval_lo; - uint64_t big = (uint64_t)(int64_t)rval_full * (0x5851F42D4C957F2DULL * paired + 0x14057B7EF767814FULL); - uint32_t carry = (uint32_t)(((uint64_t)(rval_lo * (1284865837u * rval_lo - 144211633u)) + seed_lo) >> 32); - uint32_t new_hi = seed_lo + carry + (uint32_t)(big >> 32); + uint64_t big = (uint64_t)rval_full * (0x5851F42D4C957F2DULL * paired + 0x14057B7EF767814FULL); + uint32_t carry = ((uint64_t)v9 + (uint64_t)seed_lo) > 0xFFFFFFFFULL ? 1 : 0; + uint32_t new_hi = seed_hi + carry + (uint32_t)(big >> 32); this->rval = ((int64_t)new_hi << 32) | (int64_t)new_lo; return result; @@ -209,15 +206,18 @@ void Layer::init(int64_t worldSeed) if (parent != nullptr) parent->init(worldSeed); - uint32_t ws = (uint32_t)worldSeed; - int64_t m = this->seedMixup; + int64_t m = this->seedMixup; + int64_t val = (int64_t)(uint32_t)worldSeed; - uint32_t v12 = ws * (1284865837u * ws - 144211633u); - int64_t sum1 = (int64_t)(int32_t)v12 + m; - uint32_t v14_lo = (uint32_t)sum1 * (1284865837u * (uint32_t)sum1 - 144211633u); - int64_t sum2 = (int64_t)(int32_t)v14_lo + m; + + uint32_t lo = (uint32_t)val; + uint64_t paired = ((uint64_t)lo << 32) | (uint64_t)lo; + val = val * (int64_t)(0x5851F42D4C957F2DULL * paired + 0x14057B7EF767814FULL) + m; - this->seed = sum2 * (0x5851F42D4C957F2DLL * sum2 + 0x14057B7EF767814FLL) + m; + val = val * (0x5851F42D4C957F2DLL * val + 0x14057B7EF767814FLL) + m; + val = val * (0x5851F42D4C957F2DLL * val + 0x14057B7EF767814FLL) + m; + + this->seed = val; } bool Layer::isOcean(int biomeId) diff --git a/Minecraft.World/ShoreLayer.cpp b/Minecraft.World/ShoreLayer.cpp index acf31f0d..8aee931d 100644 --- a/Minecraft.World/ShoreLayer.cpp +++ b/Minecraft.World/ShoreLayer.cpp @@ -1,69 +1,125 @@ -#include "stdafx.h" +#include "stdafx.h" #include "net.minecraft.world.level.newbiome.layer.h" #include "net.minecraft.world.level.biome.h" +#include "IntCache.h" ShoreLayer::ShoreLayer(int64_t seed, shared_ptr parent, int64_t seedMixup) : Layer(seedMixup) { this->parent = parent; } +static bool isJungleCompatible(int id) +{ + if (id == Biome::ocean->id || id == Biome::deepOcean->id) + return true; + + Biome* b = Biome::getBiome(id); + if (b != nullptr && b->isSame(Biome::jungle)) + return true; + + return id == Biome::jungleEdge->id || id == Biome::jungle->id || id == Biome::jungleHills->id || + id == Biome::forest->id || id == Biome::forestHills->id || id == Biome::taiga->id || + (b != nullptr && b->hasSnow()); +} + +void ShoreLayer::replaceIfNeighborOcean(intArray& b, intArray& result, int x, int y, int w, int old, int replacement) +{ + if (isOcean(old)) + { + result[x + y * w] = old; + return; + } + + int stride = w + 2; + int north = b[(x + 1) + y * stride]; + int east = b[(x + 2) + (y + 1) * stride]; + int west = b[(x + 0) + (y + 1) * stride]; + int south = b[(x + 1) + (y + 2) * stride]; + + if (isOcean(north) || isOcean(east) || isOcean(west) || isOcean(south)) + { + result[x + y * w] = replacement; + } + else + { + result[x + y * w] = old; + } +} + intArray ShoreLayer::getArea(int xo, int yo, int w, int h) { - intArray b = parent->getArea(xo - 1, yo - 1, w + 2, h + 2); - intArray result = IntCache::allocate(w * h); - for (int y = 0; y < h; y++) - { - for (int x = 0; x < w; x++) - { - initRandom(x + xo, y + yo); - int old = b[(x + 1) + (y + 1) * (w + 2)]; - int _n = b[(x + 1) + (y + 0) * (w + 2)]; - int _e = b[(x + 2) + (y + 1) * (w + 2)]; - int _w = b[(x + 0) + (y + 1) * (w + 2)]; - int _s = b[(x + 1) + (y + 2) * (w + 2)]; + intArray b = parent->getArea(xo - 1, yo - 1, w + 2, h + 2); + intArray result = IntCache::allocate(w * h); - if (old == Biome::mushroomIsland->id) - { - if (_n == Biome::ocean->id || _e == Biome::ocean->id || - _w == Biome::ocean->id || _s == Biome::ocean->id || - _n == Biome::deepOcean->id || _e == Biome::deepOcean->id || - _w == Biome::deepOcean->id || _s == Biome::deepOcean->id) - result[x + y * w] = Biome::mushroomIslandShore->id; - else - result[x + y * w] = old; - } - else if (old != Biome::ocean->id && old != Biome::deepOcean->id && - old != Biome::river->id && old != Biome::swampland->id && - old != Biome::extremeHills->id) - { - if (_n == Biome::ocean->id || _e == Biome::ocean->id || - _w == Biome::ocean->id || _s == Biome::ocean->id || - _n == Biome::deepOcean->id || _e == Biome::deepOcean->id || - _w == Biome::deepOcean->id || _s == Biome::deepOcean->id) - { - if (old == Biome::taiga->id || old == Biome::taigaHills->id || - old == Biome::megaTaiga->id || old == Biome::megaTaigaHills->id || - old == Biome::coldTaiga->id || old == Biome::coldTaigaHills->id) - result[x + y * w] = Biome::coldBeach->id; - else - result[x + y * w] = Biome::beaches->id; - } - else - result[x + y * w] = old; - } - else if (old == Biome::extremeHills->id) - { - if (_n != Biome::extremeHills->id || _e != Biome::extremeHills->id || - _w != Biome::extremeHills->id || _s != Biome::extremeHills->id) - result[x + y * w] = Biome::smallerExtremeHills->id; - else - result[x + y * w] = old; - } - else - { - result[x + y * w] = old; - } - } - } - return result; + for (int y = 0; y < h; y++) + { + for (int x = 0; x < w; x++) + { + initRandom(x + xo, y + yo); + int old = b[(x + 1) + (y + 1) * (w + 2)]; + int _n = b[(x + 1) + (y + 0) * (w + 2)]; + int _e = b[(x + 2) + (y + 1) * (w + 2)]; + int _w = b[(x + 0) + (y + 1) * (w + 2)]; + int _s = b[(x + 1) + (y + 2) * (w + 2)]; + + if (old == Biome::mushroomIsland->id) + { + if (_n == Biome::ocean->id || _e == Biome::ocean->id || _w == Biome::ocean->id || _s == Biome::ocean->id) + { + result[x + y * w] = Biome::mushroomIslandShore->id; + } + else + { + result[x + y * w] = old; + } + } + else if (old == Biome::jungle->id || old == Biome::jungleHills->id || old == Biome::jungleEdge->id) + { + if (isJungleCompatible(_n) && isJungleCompatible(_e) && isJungleCompatible(_w) && isJungleCompatible(_s)) + { + if (!isOcean(_n) && !isOcean(_e) && !isOcean(_w) && !isOcean(_s)) + { + result[x + y * w] = old; + } + else + { + result[x + y * w] = Biome::jungleEdge->id; + } + } + else + { + result[x + y * w] = Biome::beaches->id; + } + } + else if (old == Biome::mesa->id || old == Biome::mesaPlateauF->id || old == Biome::mesaPlateau->id) + { + replaceIfNeighborOcean(b, result, x, y, w, old, Biome::mesa->id); + } + else if (Biome::getBiome(old) != nullptr && Biome::getBiome(old)->hasSnow()) + { + replaceIfNeighborOcean(b, result, x, y, w, old, Biome::coldBeach->id); + } + else if (old == Biome::extremeHills->id || old == Biome::extremeHills_plus->id) + { + replaceIfNeighborOcean(b, result, x, y, w, old, Biome::stoneBeach->id); + } + else if (old == Biome::ocean->id || old == Biome::deepOcean->id || old == Biome::river->id || old == Biome::swampland->id) + { + result[x + y * w] = old; + } + else + { + if (isOcean(_n) || isOcean(_e) || isOcean(_w) || isOcean(_s)) + { + result[x + y * w] = Biome::beaches->id; + } + else + { + result[x + y * w] = old; + } + } + } + } + + return result; } \ No newline at end of file diff --git a/Minecraft.World/ShoreLayer.h b/Minecraft.World/ShoreLayer.h index cbae390f..af3d1771 100644 --- a/Minecraft.World/ShoreLayer.h +++ b/Minecraft.World/ShoreLayer.h @@ -6,4 +6,6 @@ class ShoreLayer : public Layer public: ShoreLayer(int64_t seed, shared_ptr parent, int64_t seedMixup); virtual intArray getArea(int xo, int yo, int w, int h); +private: + void replaceIfNeighborOcean(intArray& b, intArray& result, int x, int y, int w, int old, int replacement); }; \ No newline at end of file diff --git a/Minecraft.World/VoronoiZoom.cpp b/Minecraft.World/VoronoiZoom.cpp index 46da5c71..1b403e96 100644 --- a/Minecraft.World/VoronoiZoom.cpp +++ b/Minecraft.World/VoronoiZoom.cpp @@ -2,7 +2,7 @@ #include "net.minecraft.world.level.newbiome.layer.h" #include "System.h" -VoronoiZoom::VoronoiZoom(int64_t seed, shared_ptr parent, int64_t seedMixup) : Layer(seed) +VoronoiZoom::VoronoiZoom(int64_t seed, shared_ptr parent, int64_t seedMixup) : Layer(seedMixup) { this->parent = parent; }