aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/RandomLevelSource.cpp
diff options
context:
space:
mode:
authordaoge <3523206925@qq.com>2026-03-03 03:04:10 +0800
committerGitHub <noreply@github.com>2026-03-03 03:04:10 +0800
commitb3feddfef372618c8a9d7a0abcaf18cfad866c18 (patch)
tree267761c3bb39241ba5c347bfbe2254d06686e287 /Minecraft.World/RandomLevelSource.cpp
parent84c31a2331f7a0ec85b9d438992e244f60e5020f (diff)
feat: TU19 (Dec 2014) Features & Content (#155)
* try to resolve merge conflict * feat: TU19 (Dec 2014) Features & Content (#32) * December 2014 files * Working release build * Fix compilation issues * Add sound to Windows64Media * Add DLC content and force Tutorial DLC * Revert "Add DLC content and force Tutorial DLC" This reverts commit 97a43994725008e35fceb984d5549df9c8cea470. * Disable broken light packing * Disable breakpoint during DLC texture map load Allows DLC loading but the DLC textures are still broken * Fix post build not working * ... * fix vs2022 build * fix cmake build --------- Co-authored-by: Loki <lokirautio@gmail.com>
Diffstat (limited to 'Minecraft.World/RandomLevelSource.cpp')
-rw-r--r--Minecraft.World/RandomLevelSource.cpp768
1 files changed, 451 insertions, 317 deletions
diff --git a/Minecraft.World/RandomLevelSource.cpp b/Minecraft.World/RandomLevelSource.cpp
index 4e26134a..2b93578a 100644
--- a/Minecraft.World/RandomLevelSource.cpp
+++ b/Minecraft.World/RandomLevelSource.cpp
@@ -7,6 +7,7 @@
#include "net.minecraft.world.level.levelgen.synth.h"
#include "net.minecraft.world.level.tile.h"
#include "net.minecraft.world.level.storage.h"
+#include "net.minecraft.world.entity.h"
#include "RandomLevelSource.h"
#ifdef __PS3__
@@ -17,6 +18,8 @@ static PerlinNoise_DataIn g_lperlinNoise2_SPU __attribute__((__aligned__(16)));
static PerlinNoise_DataIn g_perlinNoise1_SPU __attribute__((__aligned__(16)));
static PerlinNoise_DataIn g_scaleNoise_SPU __attribute__((__aligned__(16)));
static PerlinNoise_DataIn g_depthNoise_SPU __attribute__((__aligned__(16)));
+//#define DISABLE_SPU_CODE
+
#endif
@@ -26,38 +29,40 @@ const double RandomLevelSource::SNOW_CUTOFF = 0.5;
RandomLevelSource::RandomLevelSource(Level *level, __int64 seed, bool generateStructures) : generateStructures( generateStructures )
{
m_XZSize = level->getLevelData()->getXZSize();
-
+#ifdef _LARGE_WORLDS
+ level->getLevelData()->getMoatFlags(&m_classicEdgeMoat, &m_smallEdgeMoat, &m_mediumEdgeMoat);
+#endif
caveFeature = new LargeCaveFeature();
strongholdFeature = new StrongholdFeature();
- villageFeature = new VillageFeature(0,m_XZSize);
- mineShaftFeature = new MineShaftFeature();
+ villageFeature = new VillageFeature(m_XZSize);
+ mineShaftFeature = new MineShaftFeature();
scatteredFeature = new RandomScatteredLargeFeature();
canyonFeature = new CanyonFeature();
- this->level = level;
+ this->level = level;
- random = new Random(seed);
+ random = new Random(seed);
pprandom = new Random(seed); // 4J - added, so that we can have a separate random for doing post-processing in parallel with creation
- lperlinNoise1 = new PerlinNoise(random, 16);
- lperlinNoise2 = new PerlinNoise(random, 16);
- perlinNoise1 = new PerlinNoise(random, 8);
- perlinNoise3 = new PerlinNoise(random, 4);
+ lperlinNoise1 = new PerlinNoise(random, 16);
+ lperlinNoise2 = new PerlinNoise(random, 16);
+ perlinNoise1 = new PerlinNoise(random, 8);
+ perlinNoise3 = new PerlinNoise(random, 4);
- scaleNoise = new PerlinNoise(random, 10);
- depthNoise = new PerlinNoise(random, 16);
+ scaleNoise = new PerlinNoise(random, 10);
+ depthNoise = new PerlinNoise(random, 16);
- if (FLOATING_ISLANDS)
+ if (FLOATING_ISLANDS)
{
- floatingIslandScale = new PerlinNoise(random, 10);
- floatingIslandNoise = new PerlinNoise(random, 16);
- }
+ floatingIslandScale = new PerlinNoise(random, 10);
+ floatingIslandNoise = new PerlinNoise(random, 16);
+ }
else
{
floatingIslandScale = NULL;
floatingIslandNoise = NULL;
}
- forestNoise = new PerlinNoise(random, 8);
+ forestNoise = new PerlinNoise(random, 8);
}
RandomLevelSource::~RandomLevelSource()
@@ -69,24 +74,24 @@ RandomLevelSource::~RandomLevelSource()
delete scatteredFeature;
delete canyonFeature;
- this->level = level;
+ this->level = level;
- delete random;;
- delete lperlinNoise1;
- delete lperlinNoise2;
- delete perlinNoise1;
- delete perlinNoise3;
+ delete random;;
+ delete lperlinNoise1;
+ delete lperlinNoise2;
+ delete perlinNoise1;
+ delete perlinNoise3;
- delete scaleNoise;
- delete depthNoise;
+ delete scaleNoise;
+ delete depthNoise;
- if (FLOATING_ISLANDS)
+ if (FLOATING_ISLANDS)
{
- delete floatingIslandScale;
- delete floatingIslandNoise;
- }
+ delete floatingIslandScale;
+ delete floatingIslandNoise;
+ }
- delete forestNoise;
+ delete forestNoise;
if( pows.data != NULL ) delete [] pows.data;
}
@@ -97,115 +102,225 @@ LARGE_INTEGER g_totalPrepareHeightsTime = {0,0};
LARGE_INTEGER g_averagePrepareHeightsTime = {0, 0};
+
+
+
+
+#ifdef _LARGE_WORLDS
+
+int RandomLevelSource::getMinDistanceToEdge(int xxx, int zzz, int worldSize, float falloffStart)
+{
+ // Get distance to edges of world in x
+ // we have to do a proper line dist check here
+ int min = -worldSize/2;
+ int max = (worldSize/2)-1;
+
+ // // only check if either x or z values are within the falloff
+ // if(xxx > (min - falloffStart)
+
+ Vec3* topLeft = Vec3::newTemp(min, 0, min);
+ Vec3* topRight = Vec3::newTemp(max, 0, min);
+ Vec3* bottomLeft = Vec3::newTemp(min, 0, max);
+ Vec3* bottomRight = Vec3::newTemp(max, 0, max);
+
+ float closest = falloffStart;
+ float dist;
+ // make sure we're in range of the edges before we do a full distance check
+ if( (xxx > (min-falloffStart) && xxx < (min+falloffStart)) ||
+ (xxx > (max-falloffStart) && xxx < (max+falloffStart)) )
+ {
+ Vec3* point = Vec3::newTemp(xxx, 0, zzz);
+ if(xxx>0)
+ dist = point->distanceFromLine(topRight, bottomRight);
+ else
+ dist = point->distanceFromLine(topLeft, bottomLeft);
+ closest = dist;
+ }
+
+ // make sure we're in range of the edges before we do a full distance check
+ if( (zzz > (min-falloffStart) && zzz < (min+falloffStart)) ||
+ (zzz > (max-falloffStart) && zzz < (max+falloffStart)) )
+ {
+ Vec3* point = Vec3::newTemp(xxx, 0, zzz);
+ if(zzz>0)
+ dist = point->distanceFromLine(bottomLeft, bottomRight);
+ else
+ dist = point->distanceFromLine(topLeft, topRight);
+ if(dist<closest)
+ closest = dist;
+ }
+
+ return closest;
+}
+
+
+float RandomLevelSource::getHeightFalloff(int xxx, int zzz, int* pEMin)
+{
+ ///////////////////////////////////////////////////////////////////
+ // 4J - add this chunk of code to make land "fall-off" at the edges of
+ // a finite world - size of that world is currently hard-coded in here
+ const int worldSize = m_XZSize * 16;
+ const int falloffStart = 32; // chunks away from edge were we start doing fall-off
+ const float falloffMax = 128.0f; // max value we need to get to falloff by the edge of the map
+
+ float comp = 0.0f;
+ int emin = getMinDistanceToEdge(xxx, zzz, worldSize, falloffStart);
+ // check if we have a larger world that should have moats
+ int expandedWorldSizes[3] = {LEVEL_WIDTH_CLASSIC*16,
+ LEVEL_WIDTH_SMALL*16,
+ LEVEL_WIDTH_MEDIUM*16};
+ bool expandedMoatValues[3] = {m_classicEdgeMoat, m_smallEdgeMoat, m_mediumEdgeMoat};
+ for(int i=0;i<3;i++)
+ {
+ if(expandedMoatValues[i] && (worldSize > expandedWorldSizes[i]))
+ {
+ // this world has been expanded, with moat settings, so we need fallofs at this edges too
+ int eminMoat = getMinDistanceToEdge(xxx, zzz, expandedWorldSizes[i], falloffStart);
+ if(eminMoat < emin)
+ {
+ emin = eminMoat;
+ }
+ }
+ }
+
+ // Calculate how much we want the world to fall away, if we're in the defined region to do so
+ if( emin < falloffStart )
+ {
+ int falloff = falloffStart - emin;
+ comp = ((float)falloff / (float)falloffStart ) * falloffMax;
+ }
+ *pEMin = emin;
+ return comp;
+ // 4J - end of extra code
+ ///////////////////////////////////////////////////////////////////
+}
+
+#else
+
+
+// MGH - go back to using the simpler version for PS3/vita/360, as it was causing a lot of slow down on the tuturial generation
+float RandomLevelSource::getHeightFalloff(int xxx, int zzz, int* pEMin)
+{
+ ///////////////////////////////////////////////////////////////////
+ // 4J - add this chunk of code to make land "fall-off" at the edges of
+ // a finite world - size of that world is currently hard-coded in here
+ const int worldSize = m_XZSize * 16;
+ const int falloffStart = 32; // chunks away from edge were we start doing fall-off
+ const float falloffMax = 128.0f; // max value we need to get to falloff by the edge of the map
+
+ // Get distance to edges of world in x
+ int xxx0 = xxx + ( worldSize / 2 );
+ if( xxx0 < 0 ) xxx0 = 0;
+ int xxx1 = ( ( worldSize / 2 ) - 1 ) - xxx;
+ if( xxx1 < 0 ) xxx1 = 0;
+
+ // Get distance to edges of world in z
+ int zzz0 = zzz + ( worldSize / 2 );
+ if( zzz0 < 0 ) zzz0 = 0;
+ int zzz1 = ( ( worldSize / 2 ) - 1 ) - zzz;
+ if( zzz1 < 0 ) zzz1 = 0;
+
+ // Get min distance to any edge
+ int emin = xxx0;
+ if (xxx1 < emin ) emin = xxx1;
+ if (zzz0 < emin ) emin = zzz0;
+ if (zzz1 < emin ) emin = zzz1;
+
+ float comp = 0.0f;
+
+ // Calculate how much we want the world to fall away, if we're in the defined region to do so
+ if( emin < falloffStart )
+ {
+ int falloff = falloffStart - emin;
+ comp = ((float)falloff / (float)falloffStart ) * falloffMax;
+ }
+ // 4J - end of extra code
+ ///////////////////////////////////////////////////////////////////
+ *pEMin = emin;
+ return comp;
+}
+
+#endif // _LARGE_WORLDS
+
void RandomLevelSource::prepareHeights(int xOffs, int zOffs, byteArray blocks)
{
LARGE_INTEGER startTime;
- int xChunks = 16 / CHUNK_WIDTH;
+ int xChunks = 16 / CHUNK_WIDTH;
int yChunks = Level::genDepth / CHUNK_HEIGHT;
int waterHeight = level->seaLevel;
- int xSize = xChunks + 1;
- int ySize = Level::genDepth / CHUNK_HEIGHT + 1;
- int zSize = xChunks + 1;
+ int xSize = xChunks + 1;
+ int ySize = Level::genDepth / CHUNK_HEIGHT + 1;
+ int zSize = xChunks + 1;
BiomeArray biomes; // 4J created locally here for thread safety, java has this as a class member
level->getBiomeSource()->getRawBiomeBlock(biomes, xOffs * CHUNK_WIDTH - 2, zOffs * CHUNK_WIDTH - 2, xSize + 5, zSize + 5);
doubleArray buffer; // 4J - used to be declared with class level scope but tidying up for thread safety reasons
- buffer = getHeights(buffer, xOffs * xChunks, 0, zOffs * xChunks, xSize, ySize, zSize, biomes);
+ buffer = getHeights(buffer, xOffs * xChunks, 0, zOffs * xChunks, xSize, ySize, zSize, biomes);
QueryPerformanceCounter(&startTime);
- for (int xc = 0; xc < xChunks; xc++)
+ for (int xc = 0; xc < xChunks; xc++)
{
- for (int zc = 0; zc < xChunks; zc++)
+ for (int zc = 0; zc < xChunks; zc++)
{
- for (int yc = 0; yc < yChunks; yc++)
+ for (int yc = 0; yc < yChunks; yc++)
{
- double yStep = 1 / (double) CHUNK_HEIGHT;
- double s0 = buffer[((xc + 0) * zSize + (zc + 0)) * ySize + (yc + 0)];
- double s1 = buffer[((xc + 0) * zSize + (zc + 1)) * ySize + (yc + 0)];
- double s2 = buffer[((xc + 1) * zSize + (zc + 0)) * ySize + (yc + 0)];
- double s3 = buffer[((xc + 1) * zSize + (zc + 1)) * ySize + (yc + 0)];
-
- double s0a = (buffer[((xc + 0) * zSize + (zc + 0)) * ySize + (yc + 1)] - s0) * yStep;
- double s1a = (buffer[((xc + 0) * zSize + (zc + 1)) * ySize + (yc + 1)] - s1) * yStep;
- double s2a = (buffer[((xc + 1) * zSize + (zc + 0)) * ySize + (yc + 1)] - s2) * yStep;
- double s3a = (buffer[((xc + 1) * zSize + (zc + 1)) * ySize + (yc + 1)] - s3) * yStep;
-
- for (int y = 0; y < CHUNK_HEIGHT; y++)
+ double yStep = 1 / (double) CHUNK_HEIGHT;
+ double s0 = buffer[((xc + 0) * zSize + (zc + 0)) * ySize + (yc + 0)];
+ double s1 = buffer[((xc + 0) * zSize + (zc + 1)) * ySize + (yc + 0)];
+ double s2 = buffer[((xc + 1) * zSize + (zc + 0)) * ySize + (yc + 0)];
+ double s3 = buffer[((xc + 1) * zSize + (zc + 1)) * ySize + (yc + 0)];
+
+ double s0a = (buffer[((xc + 0) * zSize + (zc + 0)) * ySize + (yc + 1)] - s0) * yStep;
+ double s1a = (buffer[((xc + 0) * zSize + (zc + 1)) * ySize + (yc + 1)] - s1) * yStep;
+ double s2a = (buffer[((xc + 1) * zSize + (zc + 0)) * ySize + (yc + 1)] - s2) * yStep;
+ double s3a = (buffer[((xc + 1) * zSize + (zc + 1)) * ySize + (yc + 1)] - s3) * yStep;
+
+ for (int y = 0; y < CHUNK_HEIGHT; y++)
{
- double xStep = 1 / (double) CHUNK_WIDTH;
+ double xStep = 1 / (double) CHUNK_WIDTH;
- double _s0 = s0;
- double _s1 = s1;
- double _s0a = (s2 - s0) * xStep;
- double _s1a = (s3 - s1) * xStep;
+ double _s0 = s0;
+ double _s1 = s1;
+ double _s0a = (s2 - s0) * xStep;
+ double _s1a = (s3 - s1) * xStep;
- for (int x = 0; x < CHUNK_WIDTH; x++)
+ for (int x = 0; x < CHUNK_WIDTH; x++)
{
- int offs = (x + xc * CHUNK_WIDTH) << Level::genDepthBitsPlusFour | (0 + zc * CHUNK_WIDTH) << Level::genDepthBits | (yc * CHUNK_HEIGHT + y);
- int step = 1 << Level::genDepthBits;
+ int offs = (x + xc * CHUNK_WIDTH) << Level::genDepthBitsPlusFour | (0 + zc * CHUNK_WIDTH) << Level::genDepthBits | (yc * CHUNK_HEIGHT + y);
+ int step = 1 << Level::genDepthBits;
offs -= step;
- double zStep = 1 / (double) CHUNK_WIDTH;
+ double zStep = 1 / (double) CHUNK_WIDTH;
- double val = _s0;
- double vala = (_s1 - _s0) * zStep;
+ double val = _s0;
+ double vala = (_s1 - _s0) * zStep;
val -= vala;
- for (int z = 0; z < CHUNK_WIDTH; z++)
+ for (int z = 0; z < CHUNK_WIDTH; z++)
{
- ///////////////////////////////////////////////////////////////////
- // 4J - add this chunk of code to make land "fall-off" at the edges of
- // a finite world - size of that world is currently hard-coded in here
- const int worldSize = m_XZSize * 16;
- const int falloffStart = 32; // chunks away from edge were we start doing fall-off
- const float falloffMax = 128.0f; // max value we need to get to falloff by the edge of the map
-
+// 4J Stu - I have removed all uses of the new getHeightFalloff function for now as we had some problems with PS3/PSVita world generation
+// I have fixed the non large worlds method, however we will be happier if the current builds go out with completely old code
+// We can put the new code back in mid-november 2014 once those PS3/Vita builds are gone (and the PS4 doesn't have world enlarging in these either anyway)
int xxx = ( ( xOffs * 16 ) + x + ( xc * CHUNK_WIDTH ) );
int zzz = ( ( zOffs * 16 ) + z + ( zc * CHUNK_WIDTH ) );
+ int emin;
+ float comp = getHeightFalloff(xxx, zzz, &emin);
- // Get distance to edges of world in x
- int xxx0 = xxx + ( worldSize / 2 );
- if( xxx0 < 0 ) xxx0 = 0;
- int xxx1 = ( ( worldSize / 2 ) - 1 ) - xxx;
- if( xxx1 < 0 ) xxx1 = 0;
-
- // Get distance to edges of world in z
- int zzz0 = zzz + ( worldSize / 2 );
- if( zzz0 < 0 ) zzz0 = 0;
- int zzz1 = ( ( worldSize / 2 ) - 1 ) - zzz;
- if( zzz1 < 0 ) zzz1 = 0;
-
- // Get min distance to any edge
- int emin = xxx0;
- if (xxx1 < emin ) emin = xxx1;
- if (zzz0 < emin ) emin = zzz0;
- if (zzz1 < emin ) emin = zzz1;
-
- float comp = 0.0f;
-
- // Calculate how much we want the world to fall away, if we're in the defined region to do so
- if( emin < falloffStart )
- {
- int falloff = falloffStart - emin;
- comp = ((float)falloff / (float)falloffStart ) * falloffMax;
- }
- // 4J - end of extra code
- ///////////////////////////////////////////////////////////////////
// 4J - slightly rearranged this code (as of java 1.0.1 merge) to better fit with
// changes we've made edge-of-world things - original sets blocks[offs += step] directly
// here rather than setting a tileId
int tileId = 0;
// 4J - this comparison used to just be with 0.0f but is now varied by block above
- if ((val += vala) > comp)
+ if ((val += vala) > comp)
{
- tileId = (byte) Tile::rock_Id;
- }
+ tileId = (byte) Tile::stone_Id;
+ }
else if (yc * CHUNK_HEIGHT + y < waterHeight)
{
- tileId = (byte) Tile::calmWater_Id;
- }
+ tileId = (byte) Tile::calmWater_Id;
+ }
// 4J - more extra code to make sure that the column at the edge of the world is just water & rock, to match the infinite sea that
// continues on after the edge of the world.
@@ -213,24 +328,24 @@ void RandomLevelSource::prepareHeights(int xOffs, int zOffs, byteArray blocks)
if( emin == 0 )
{
// This matches code in MultiPlayerChunkCache that makes the geometry which continues at the edge of the world
- if( yc * CHUNK_HEIGHT + y <= ( level->getSeaLevel() - 10 ) ) tileId = Tile::rock_Id;
+ if( yc * CHUNK_HEIGHT + y <= ( level->getSeaLevel() - 10 ) ) tileId = Tile::stone_Id;
else if( yc * CHUNK_HEIGHT + y < level->getSeaLevel() ) tileId = Tile::calmWater_Id;
}
blocks[offs += step] = tileId;
- }
- _s0 += _s0a;
- _s1 += _s1a;
- }
-
- s0 += s0a;
- s1 += s1a;
- s2 += s2a;
- s3 += s3a;
- }
- }
- }
- }
+ }
+ _s0 += _s0a;
+ _s1 += _s1a;
+ }
+
+ s0 += s0a;
+ s1 += s1a;
+ s2 += s2a;
+ s3 += s3a;
+ }
+ }
+ }
+ }
LARGE_INTEGER endTime;
QueryPerformanceCounter(&endTime);
LARGE_INTEGER timeInFunc;
@@ -248,26 +363,26 @@ void RandomLevelSource::prepareHeights(int xOffs, int zOffs, byteArray blocks)
void RandomLevelSource::buildSurfaces(int xOffs, int zOffs, byteArray blocks, BiomeArray biomes)
{
- int waterHeight = level->seaLevel;
+ int waterHeight = level->seaLevel;
- double s = 1 / 32.0;
+ double s = 1 / 32.0;
doubleArray depthBuffer(16*16); // 4J - used to be declared with class level scope but moved here for thread safety
- depthBuffer = perlinNoise3->getRegion(depthBuffer, xOffs * 16, zOffs * 16, 0, 16, 16, 1, s * 2, s * 2, s * 2);
+ depthBuffer = perlinNoise3->getRegion(depthBuffer, xOffs * 16, zOffs * 16, 0, 16, 16, 1, s * 2, s * 2, s * 2);
- for (int x = 0; x < 16; x++)
+ for (int x = 0; x < 16; x++)
{
- for (int z = 0; z < 16; z++)
+ for (int z = 0; z < 16; z++)
{
- Biome *b = biomes[z + x * 16];
+ Biome *b = biomes[z + x * 16];
float temp = b->getTemperature();
- int runDepth = (int) (depthBuffer[x + z * 16] / 3 + 3 + random->nextDouble() * 0.25);
+ int runDepth = (int) (depthBuffer[x + z * 16] / 3 + 3 + random->nextDouble() * 0.25);
- int run = -1;
+ int run = -1;
- byte top = b->topMaterial;
- byte material = b->material;
+ byte top = b->topMaterial;
+ byte material = b->material;
LevelGenerationOptions *lgo = app.getLevelGenerationOptions();
if(lgo != NULL)
@@ -275,70 +390,69 @@ void RandomLevelSource::buildSurfaces(int xOffs, int zOffs, byteArray blocks, Bi
lgo->getBiomeOverride(b->id,material,top);
}
- for (int y = Level::genDepthMinusOne; y >= 0; y--)
+ for (int y = Level::genDepthMinusOne; y >= 0; y--)
{
- int offs = (z * 16 + x) * Level::genDepth + y;
+ int offs = (z * 16 + x) * Level::genDepth + y;
if (y <= 1 + random->nextInt(2)) // 4J - changed to make the bedrock not have bits you can get stuck in
-// if (y <= 0 + random->nextInt(5))
+ // if (y <= 0 + random->nextInt(5))
{
- blocks[offs] = (byte) Tile::unbreakable_Id;
- }
+ blocks[offs] = (byte) Tile::unbreakable_Id;
+ }
else
{
- int old = blocks[offs];
+ int old = blocks[offs];
- if (old == 0)
+ if (old == 0)
{
- run = -1;
- }
- else if (old == Tile::rock_Id)
+ run = -1;
+ }
+ else if (old == Tile::stone_Id)
{
- if (run == -1)
+ if (run == -1)
{
- if (runDepth <= 0)
+ if (runDepth <= 0)
{
- top = 0;
- material = (byte) Tile::rock_Id;
- }
+ top = 0;
+ material = (byte) Tile::stone_Id;
+ }
else if (y >= waterHeight - 4 && y <= waterHeight + 1)
{
- top = b->topMaterial;
+ top = b->topMaterial;
material = b->material;
if(lgo != NULL)
{
lgo->getBiomeOverride(b->id,material,top);
}
- }
+ }
- if (y < waterHeight && top == 0)
+ if (y < waterHeight && top == 0)
{
- if (temp < 0.15f) top = (byte) Tile::ice_Id;
- else top = (byte) Tile::calmWater_Id;
- }
-
- run = runDepth;
- if (y >= waterHeight - 1) blocks[offs] = top;
- else blocks[offs] = material;
- }
+ if (temp < 0.15f) top = (byte) Tile::ice_Id;
+ else top = (byte) Tile::calmWater_Id;
+ }
+
+ run = runDepth;
+ if (y >= waterHeight - 1) blocks[offs] = top;
+ else blocks[offs] = material;
+ }
else if (run > 0)
{
- run--;
- blocks[offs] = material;
+ run--;
+ blocks[offs] = material;
- // place a few sandstone blocks beneath sand
- // runs
- if (run == 0 && material == Tile::sand_Id)
+ // place a few sandstone blocks beneath sand runs
+ if (run == 0 && material == Tile::sand_Id)
{
- run = random->nextInt(4);
- material = (byte) Tile::sandStone_Id;
- }
- }
- }
- }
- }
- }
- }
+ run = random->nextInt(4);
+ material = (byte) Tile::sandStone_Id;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
delete [] depthBuffer.data;
@@ -351,28 +465,28 @@ LevelChunk *RandomLevelSource::create(int x, int z)
LevelChunk *RandomLevelSource::getChunk(int xOffs, int zOffs)
{
- random->setSeed(xOffs * 341873128712l + zOffs * 132897987541l);
+ random->setSeed(xOffs * 341873128712l + zOffs * 132897987541l);
// 4J - now allocating this with a physical alloc & bypassing general memory management so that it will get cleanly freed
int blocksSize = Level::genDepth * 16 * 16;
byte *tileData = (byte *)XPhysicalAlloc(blocksSize, MAXULONG_PTR, 4096, PAGE_READWRITE);
XMemSet128(tileData,0,blocksSize);
byteArray blocks = byteArray(tileData,blocksSize);
-// byteArray blocks = byteArray(16 * level->depth * 16);
+ // byteArray blocks = byteArray(16 * level->depth * 16);
- // LevelChunk *levelChunk = new LevelChunk(level, blocks, xOffs, zOffs); // 4J - moved to below
+ // LevelChunk *levelChunk = new LevelChunk(level, blocks, xOffs, zOffs); // 4J - moved to below
prepareHeights(xOffs, zOffs, blocks);
// 4J - Some changes made here to how biomes, temperatures and downfalls are passed around for thread safety
BiomeArray biomes;
- level->getBiomeSource()->getBiomeBlock(biomes, xOffs * 16, zOffs * 16, 16, 16, true);
+ level->getBiomeSource()->getBiomeBlock(biomes, xOffs * 16, zOffs * 16, 16, 16, true);
- buildSurfaces(xOffs, zOffs, blocks, biomes);
+ buildSurfaces(xOffs, zOffs, blocks, biomes);
delete [] biomes.data;
- caveFeature->apply(this, level, xOffs, zOffs, blocks);
+ caveFeature->apply(this, level, xOffs, zOffs, blocks);
// 4J Stu Design Change - 1.8 gen goes stronghold, mineshaft, village, canyon
// this changed in 1.2 to canyon, mineshaft, village, stronghold
// This change makes sense as it stops canyons running through other structures
@@ -384,19 +498,19 @@ LevelChunk *RandomLevelSource::getChunk(int xOffs, int zOffs)
strongholdFeature->apply(this, level, xOffs, zOffs, blocks);
scatteredFeature->apply(this, level, xOffs, zOffs, blocks);
}
-// canyonFeature.apply(this, level, xOffs, zOffs, blocks);
- // townFeature.apply(this, level, xOffs, zOffs, blocks);
- // addCaves(xOffs, zOffs, blocks);
- // addTowns(xOffs, zOffs, blocks);
+ // canyonFeature.apply(this, level, xOffs, zOffs, blocks);
+ // townFeature.apply(this, level, xOffs, zOffs, blocks);
+ // addCaves(xOffs, zOffs, blocks);
+ // addTowns(xOffs, zOffs, blocks);
-// levelChunk->recalcHeightmap(); // 4J - removed & moved into its own method
+ // levelChunk->recalcHeightmap(); // 4J - removed & moved into its own method
// 4J - this now creates compressed block data from the blocks array passed in, so moved it until after the blocks are actually finalised. We also
// now need to free the passed in blocks as the LevelChunk doesn't use the passed in allocation anymore.
LevelChunk *levelChunk = new LevelChunk(level, blocks, xOffs, zOffs);
XPhysicalFree(tileData);
- return levelChunk;
+ return levelChunk;
}
// 4J - removed & moved into its own method from getChunk, so we can call recalcHeightmap after the chunk is added into the cache. Without
@@ -411,10 +525,10 @@ void RandomLevelSource::lightChunk(LevelChunk *lc)
doubleArray RandomLevelSource::getHeights(doubleArray buffer, int x, int y, int z, int xSize, int ySize, int zSize, BiomeArray& biomes)
{
- if (buffer.data == NULL)
+ if (buffer.data == NULL)
{
- buffer = doubleArray(xSize * ySize * zSize);
- }
+ buffer = doubleArray(xSize * ySize * zSize);
+ }
if (pows.data == NULL)
{
pows = floatArray(5 * 5);
@@ -428,16 +542,16 @@ doubleArray RandomLevelSource::getHeights(doubleArray buffer, int x, int y, int
}
}
- double s = 1 * 684.412;
- double hs = 1 * 684.412;
+ double s = 1 * 684.412;
+ double hs = 1 * 684.412;
doubleArray pnr, ar, br, sr, dr, fi, fis; // 4J - used to be declared with class level scope but moved here for thread safety
- if (FLOATING_ISLANDS)
+ if (FLOATING_ISLANDS)
{
- fis = floatingIslandScale->getRegion(fis, x, y, z, xSize, 1, zSize, 1.0, 0, 1.0);
- fi = floatingIslandNoise->getRegion(fi, x, y, z, xSize, 1, zSize, 500.0, 0, 500.0);
- }
+ fis = floatingIslandScale->getRegion(fis, x, y, z, xSize, 1, zSize, 1.0, 0, 1.0);
+ fi = floatingIslandNoise->getRegion(fi, x, y, z, xSize, 1, zSize, 500.0, 0, 500.0);
+ }
#if defined __PS3__ && !defined DISABLE_SPU_CODE
C4JSpursJobQueue::Port port("C4JSpursJob_PerlinNoise");
@@ -459,23 +573,23 @@ doubleArray RandomLevelSource::getHeights(doubleArray buffer, int x, int y, int
port.submitJob(&perlinJob4);
port.submitJob(&perlinJob5);
port.waitForCompletion();
- #else
- sr = scaleNoise->getRegion(sr, x, z, xSize, zSize, 1.121, 1.121, 0.5);
- dr = depthNoise->getRegion(dr, x, z, xSize, zSize, 200.0, 200.0, 0.5);
- pnr = perlinNoise1->getRegion(pnr, x, y, z, xSize, ySize, zSize, s / 80.0, hs / 160.0, s / 80.0);
- ar = lperlinNoise1->getRegion(ar, x, y, z, xSize, ySize, zSize, s, hs, s);
- br = lperlinNoise2->getRegion(br, x, y, z, xSize, ySize, zSize, s, hs, s);
+#else
+ sr = scaleNoise->getRegion(sr, x, z, xSize, zSize, 1.121, 1.121, 0.5);
+ dr = depthNoise->getRegion(dr, x, z, xSize, zSize, 200.0, 200.0, 0.5);
+ pnr = perlinNoise1->getRegion(pnr, x, y, z, xSize, ySize, zSize, s / 80.0, hs / 160.0, s / 80.0);
+ ar = lperlinNoise1->getRegion(ar, x, y, z, xSize, ySize, zSize, s, hs, s);
+ br = lperlinNoise2->getRegion(br, x, y, z, xSize, ySize, zSize, s, hs, s);
#endif
x = z = 0;
- int p = 0;
- int pp = 0;
+ int p = 0;
+ int pp = 0;
- for (int xx = 0; xx < xSize; xx++)
+ for (int xx = 0; xx < xSize; xx++)
{
- for (int zz = 0; zz < zSize; zz++)
+ for (int zz = 0; zz < zSize; zz++)
{
float sss = 0;
float ddd = 0;
@@ -504,27 +618,27 @@ doubleArray RandomLevelSource::getHeights(doubleArray buffer, int x, int y, int
sss = sss * 0.9f + 0.1f;
ddd = (ddd * 4 - 1) / 8.0f;
-
- double rdepth = (dr[pp] / 8000.0);
- if (rdepth < 0) rdepth = -rdepth * 0.3;
- rdepth = rdepth * 3.0 - 2.0;
- if (rdepth < 0)
+ double rdepth = (dr[pp] / 8000.0);
+ if (rdepth < 0) rdepth = -rdepth * 0.3;
+ rdepth = rdepth * 3.0 - 2.0;
+
+ if (rdepth < 0)
{
rdepth = rdepth / 2;
- if (rdepth < -1) rdepth = -1;
- rdepth = rdepth / 1.4;
- rdepth /= 2;
- }
+ if (rdepth < -1) rdepth = -1;
+ rdepth = rdepth / 1.4;
+ rdepth /= 2;
+ }
else
{
- if (rdepth > 1) rdepth = 1;
- rdepth = rdepth / 8;
- }
+ if (rdepth > 1) rdepth = 1;
+ rdepth = rdepth / 8;
+ }
- pp++;
+ pp++;
- for (int yy = 0; yy < ySize; yy++)
+ for (int yy = 0; yy < ySize; yy++)
{
double depth = ddd;
double scale = sss;
@@ -534,32 +648,32 @@ doubleArray RandomLevelSource::getHeights(doubleArray buffer, int x, int y, int
double yCenter = ySize / 2.0 + depth * 4;
- double val = 0;
+ double val = 0;
double yOffs = (yy - (yCenter)) * 12 * 128 / Level::genDepth / scale;
- if (yOffs < 0) yOffs *= 4;
+ if (yOffs < 0) yOffs *= 4;
- double bb = ar[p] / 512;
- double cc = br[p] / 512;
+ double bb = ar[p] / 512;
+ double cc = br[p] / 512;
- double v = (pnr[p] / 10 + 1) / 2;
- if (v < 0) val = bb;
- else if (v > 1) val = cc;
- else val = bb + (cc - bb) * v;
- val -= yOffs;
+ double v = (pnr[p] / 10 + 1) / 2;
+ if (v < 0) val = bb;
+ else if (v > 1) val = cc;
+ else val = bb + (cc - bb) * v;
+ val -= yOffs;
- if (yy > ySize - 4)
+ if (yy > ySize - 4)
{
- double slide = (yy - (ySize - 4)) / (4 - 1.0f);
- val = val * (1 - slide) + -10 * slide;
- }
+ double slide = (yy - (ySize - 4)) / (4 - 1.0f);
+ val = val * (1 - slide) + -10 * slide;
+ }
- buffer[p] = val;
- p++;
- }
- }
- }
+ buffer[p] = val;
+ p++;
+ }
+ }
+ }
delete [] pnr.data;
delete [] ar.data;
@@ -569,7 +683,7 @@ doubleArray RandomLevelSource::getHeights(doubleArray buffer, int x, int y, int
delete [] fi.data;
delete [] fis.data;
- return buffer;
+ return buffer;
}
@@ -580,76 +694,76 @@ bool RandomLevelSource::hasChunk(int x, int y)
void RandomLevelSource::calcWaterDepths(ChunkSource *parent, int xt, int zt)
{
- int xo = xt * 16;
- int zo = zt * 16;
- for (int x = 0; x < 16; x++)
+ int xo = xt * 16;
+ int zo = zt * 16;
+ for (int x = 0; x < 16; x++)
{
- int y = level->getSeaLevel();
- for (int z = 0; z < 16; z++)
+ int y = level->getSeaLevel();
+ for (int z = 0; z < 16; z++)
{
- int xp = xo + x + 7;
- int zp = zo + z + 7;
- int h = level->getHeightmap(xp, zp);
- if (h <= 0)
+ int xp = xo + x + 7;
+ int zp = zo + z + 7;
+ int h = level->getHeightmap(xp, zp);
+ if (h <= 0)
{
- if (level->getHeightmap(xp - 1, zp) > 0 || level->getHeightmap(xp + 1, zp) > 0 || level->getHeightmap(xp, zp - 1) > 0 || level->getHeightmap(xp, zp + 1) > 0)
+ if (level->getHeightmap(xp - 1, zp) > 0 || level->getHeightmap(xp + 1, zp) > 0 || level->getHeightmap(xp, zp - 1) > 0 || level->getHeightmap(xp, zp + 1) > 0)
{
- bool hadWater = false;
- if (hadWater || (level->getTile(xp - 1, y, zp) == Tile::calmWater_Id && level->getData(xp - 1, y, zp) < 7)) hadWater = true;
- if (hadWater || (level->getTile(xp + 1, y, zp) == Tile::calmWater_Id && level->getData(xp + 1, y, zp) < 7)) hadWater = true;
- if (hadWater || (level->getTile(xp, y, zp - 1) == Tile::calmWater_Id && level->getData(xp, y, zp - 1) < 7)) hadWater = true;
- if (hadWater || (level->getTile(xp, y, zp + 1) == Tile::calmWater_Id && level->getData(xp, y, zp + 1) < 7)) hadWater = true;
- if (hadWater)
+ bool hadWater = false;
+ if (hadWater || (level->getTile(xp - 1, y, zp) == Tile::calmWater_Id && level->getData(xp - 1, y, zp) < 7)) hadWater = true;
+ if (hadWater || (level->getTile(xp + 1, y, zp) == Tile::calmWater_Id && level->getData(xp + 1, y, zp) < 7)) hadWater = true;
+ if (hadWater || (level->getTile(xp, y, zp - 1) == Tile::calmWater_Id && level->getData(xp, y, zp - 1) < 7)) hadWater = true;
+ if (hadWater || (level->getTile(xp, y, zp + 1) == Tile::calmWater_Id && level->getData(xp, y, zp + 1) < 7)) hadWater = true;
+ if (hadWater)
{
- for (int x2 = -5; x2 <= 5; x2++)
+ for (int x2 = -5; x2 <= 5; x2++)
{
- for (int z2 = -5; z2 <= 5; z2++)
+ for (int z2 = -5; z2 <= 5; z2++)
{
- int d = (x2 > 0 ? x2 : -x2) + (z2 > 0 ? z2 : -z2);
+ int d = (x2 > 0 ? x2 : -x2) + (z2 > 0 ? z2 : -z2);
- if (d <= 5)
+ if (d <= 5)
{
- d = 6 - d;
- if (level->getTile(xp + x2, y, zp + z2) == Tile::calmWater_Id)
+ d = 6 - d;
+ if (level->getTile(xp + x2, y, zp + z2) == Tile::calmWater_Id)
{
- int od = level->getData(xp + x2, y, zp + z2);
- if (od < 7 && od < d)
+ int od = level->getData(xp + x2, y, zp + z2);
+ if (od < 7 && od < d)
{
- level->setData(xp + x2, y, zp + z2, d);
- }
- }
- }
- }
- }
- if (hadWater)
+ level->setData(xp + x2, y, zp + z2, d, Tile::UPDATE_ALL);
+ }
+ }
+ }
+ }
+ }
+ if (hadWater)
{
- level->setTileAndDataNoUpdate(xp, y, zp, Tile::calmWater_Id, 7);
- for (int y2 = 0; y2 < y; y2++)
+ level->setTileAndData(xp, y, zp, Tile::calmWater_Id, 7, Tile::UPDATE_CLIENTS);
+ for (int y2 = 0; y2 < y; y2++)
{
- level->setTileAndDataNoUpdate(xp, y2, zp, Tile::calmWater_Id, 8);
- }
- }
- }
- }
- }
- }
- }
+ level->setTileAndData(xp, y2, zp, Tile::calmWater_Id, 8, Tile::UPDATE_CLIENTS);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
// 4J - changed this to used pprandom rather than random, so that we can run it concurrently with getChunk
void RandomLevelSource::postProcess(ChunkSource *parent, int xt, int zt)
{
- HeavyTile::instaFall = true;
- int xo = xt * 16;
- int zo = zt * 16;
+ HeavyTile::instaFall = true;
+ int xo = xt * 16;
+ int zo = zt * 16;
- Biome *biome = level->getBiome(xo + 16, zo + 16);
+ Biome *biome = level->getBiome(xo + 16, zo + 16);
- if (RandomLevelSource::FLOATING_ISLANDS)
+ if (FLOATING_ISLANDS)
{
- calcWaterDepths(parent, xt, zt);
- }
+ calcWaterDepths(parent, xt, zt);
+ }
pprandom->setSeed(level->getSeed());
__int64 xScale = pprandom->nextLong() / 2 * 2 + 1;
@@ -669,15 +783,17 @@ void RandomLevelSource::postProcess(ChunkSource *parent, int xt, int zt)
PIXEndNamedEvent();
PIXBeginNamedEvent(0,"Lakes");
- if (!hasVillage && pprandom->nextInt(4) == 0)
+ if (biome != Biome::desert && biome != Biome::desertHills)
{
- int x = xo + pprandom->nextInt(16) + 8;
- int y = pprandom->nextInt(Level::genDepth);
- int z = zo + pprandom->nextInt(16) + 8;
+ if (!hasVillage && pprandom->nextInt(4) == 0)
+ {
+ int x = xo + pprandom->nextInt(16) + 8;
+ int y = pprandom->nextInt(Level::genDepth);
+ int z = zo + pprandom->nextInt(16) + 8;
- LakeFeature *calmWater = new LakeFeature(Tile::calmWater_Id);
- calmWater->place(level, pprandom, x, y, z);
- delete calmWater;
+ LakeFeature calmWater(Tile::calmWater_Id);
+ calmWater.place(level, pprandom, x, y, z);
+ }
}
PIXEndNamedEvent();
@@ -689,55 +805,58 @@ void RandomLevelSource::postProcess(ChunkSource *parent, int xt, int zt)
int z = zo + pprandom->nextInt(16) + 8;
if (y < level->seaLevel || pprandom->nextInt(10) == 0)
{
- LakeFeature *calmLava = new LakeFeature(Tile::calmLava_Id);
- calmLava->place(level, pprandom, x, y, z);
- delete calmLava;
+ LakeFeature calmLava(Tile::calmLava_Id);
+ calmLava.place(level, pprandom, x, y, z);
}
}
PIXEndNamedEvent();
PIXBeginNamedEvent(0,"Monster rooms");
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < 8; i++)
+ {
int x = xo + pprandom->nextInt(16) + 8;
int y = pprandom->nextInt(Level::genDepth);
int z = zo + pprandom->nextInt(16) + 8;
- MonsterRoomFeature *mrf = new MonsterRoomFeature();
- if (mrf->place(level, pprandom, x, y, z))
- {
- }
- delete mrf;
+ MonsterRoomFeature mrf;
+ mrf.place(level, pprandom, x, y, z);
}
PIXEndNamedEvent();
PIXBeginNamedEvent(0,"Biome decorate");
biome->decorate(level, pprandom, xo, zo);
PIXEndNamedEvent();
-
+
+ PIXBeginNamedEvent(0,"Process Schematics");
app.processSchematics(parent->getChunk(xt,zt));
+ PIXEndNamedEvent();
+ PIXBeginNamedEvent(0,"Post process mobs");
MobSpawner::postProcessSpawnMobs(level, biome, xo + 8, zo + 8, 16, 16, pprandom);
+ PIXEndNamedEvent();
+ PIXBeginNamedEvent(0,"Update ice and snow");
// 4J - brought forward from 1.2.3 to get snow back in taiga biomes
- xo += 8;
- zo += 8;
- for (int x = 0; x < 16; x++)
+ xo += 8;
+ zo += 8;
+ for (int x = 0; x < 16; x++)
{
- for (int z = 0; z < 16; z++)
+ for (int z = 0; z < 16; z++)
{
- int y = level->getTopRainBlock(xo + x, zo + z);
+ int y = level->getTopRainBlock(xo + x, zo + z);
- if (level->shouldFreezeIgnoreNeighbors(x + xo, y - 1, z + zo))
+ if (level->shouldFreezeIgnoreNeighbors(x + xo, y - 1, z + zo))
{
- level->setTileNoUpdate(x + xo, y - 1, z + zo, Tile::ice_Id); // 4J - changed from setTile, otherwise we end up creating a *lot* of dynamic water tiles as these ice tiles are set
- }
- if (level->shouldSnow(x + xo, y, z + zo))
+ level->setTileAndData(x + xo, y - 1, z + zo, Tile::ice_Id, 0, Tile::UPDATE_CLIENTS);
+ }
+ if (level->shouldSnow(x + xo, y, z + zo))
{
- level->setTile(x + xo, y, z + zo, Tile::topSnow_Id);
- }
- }
- }
+ level->setTileAndData(x + xo, y, z + zo, Tile::topSnow_Id, 0, Tile::UPDATE_CLIENTS);
+ }
+ }
+ }
+ PIXEndNamedEvent();
- HeavyTile::instaFall = false;
+ HeavyTile::instaFall = false;
}
bool RandomLevelSource::save(bool force, ProgressListener *progressListener)
@@ -762,19 +881,34 @@ wstring RandomLevelSource::gatherStats()
vector<Biome::MobSpawnerData *> *RandomLevelSource::getMobsAt(MobCategory *mobCategory, int x, int y, int z)
{
- Biome *biome = level->getBiome(x, z);
- if (biome == NULL)
+ Biome *biome = level->getBiome(x, z);
+ if (biome == NULL)
{
- return NULL;
- }
- return biome->getMobs(mobCategory);
+ return NULL;
+ }
+ if (mobCategory == MobCategory::monster && scatteredFeature->isSwamphut(x, y, z))
+ {
+ return scatteredFeature->getSwamphutEnemies();
+ }
+ return biome->getMobs(mobCategory);
}
TilePos *RandomLevelSource::findNearestMapFeature(Level *level, const wstring& featureName, int x, int y, int z)
{
- if (LargeFeature::STRONGHOLD == featureName && strongholdFeature != NULL)
+ if (LargeFeature::STRONGHOLD == featureName && strongholdFeature != NULL)
{
- return strongholdFeature->getNearestGeneratedFeature(level, x, y, z);
- }
- return NULL;
+ return strongholdFeature->getNearestGeneratedFeature(level, x, y, z);
+ }
+ return NULL;
}
+
+void RandomLevelSource::recreateLogicStructuresForChunk(int chunkX, int chunkZ)
+{
+ if (generateStructures)
+ {
+ mineShaftFeature->apply(this, level, chunkX, chunkZ, NULL);
+ villageFeature->apply(this, level, chunkX, chunkZ, NULL);
+ strongholdFeature->apply(this, level, chunkX, chunkZ, NULL);
+ scatteredFeature->apply(this, level, chunkX, chunkZ, NULL);
+ }
+} \ No newline at end of file