the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 424 lines 12 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.level.h" 3#include "net.minecraft.world.level.biome.h" 4#include "net.minecraft.world.level.levelgen.h" 5#include "net.minecraft.world.level.levelgen.feature.h" 6#include "net.minecraft.world.level.levelgen.structure.h" 7#include "net.minecraft.world.level.levelgen.synth.h" 8#include "net.minecraft.world.level.tile.h" 9#include "net.minecraft.world.level.storage.h" 10#include "TheEndLevelRandomLevelSource.h" 11 12TheEndLevelRandomLevelSource::TheEndLevelRandomLevelSource(Level *level, __int64 seed) 13{ 14 m_XZSize = END_LEVEL_MIN_WIDTH; 15 16 this->level = level; 17 18 random = new Random(seed); 19 pprandom = new Random(seed); // 4J added 20 lperlinNoise1 = new PerlinNoise(random, 16); 21 lperlinNoise2 = new PerlinNoise(random, 16); 22 perlinNoise1 = new PerlinNoise(random, 8); 23 24 scaleNoise = new PerlinNoise(random, 10); 25 depthNoise = new PerlinNoise(random, 16); 26} 27 28TheEndLevelRandomLevelSource::~TheEndLevelRandomLevelSource() 29{ 30 delete random; 31 delete pprandom; 32 delete lperlinNoise1; 33 delete lperlinNoise2; 34 delete perlinNoise1; 35 delete scaleNoise; 36 delete depthNoise; 37} 38 39void TheEndLevelRandomLevelSource::prepareHeights(int xOffs, int zOffs, byteArray blocks, BiomeArray biomes) 40{ 41 doubleArray buffer; // 4J - used to be declared with class level scope but tidying up for thread safety reasons 42 43 int xChunks = 16 / CHUNK_WIDTH; 44 45 int xSize = xChunks + 1; 46 int ySize = Level::genDepth / CHUNK_HEIGHT + 1; 47 int zSize = xChunks + 1; 48 buffer = getHeights(buffer, xOffs * xChunks, 0, zOffs * xChunks, xSize, ySize, zSize); 49 50 for (int xc = 0; xc < xChunks; xc++) 51 { 52 for (int zc = 0; zc < xChunks; zc++) 53 { 54 for (int yc = 0; yc < Level::genDepth / CHUNK_HEIGHT; yc++) 55 { 56 double yStep = 1 / (double) CHUNK_HEIGHT; 57 double s0 = buffer[((xc + 0) * zSize + (zc + 0)) * ySize + (yc + 0)]; 58 double s1 = buffer[((xc + 0) * zSize + (zc + 1)) * ySize + (yc + 0)]; 59 double s2 = buffer[((xc + 1) * zSize + (zc + 0)) * ySize + (yc + 0)]; 60 double s3 = buffer[((xc + 1) * zSize + (zc + 1)) * ySize + (yc + 0)]; 61 62 double s0a = (buffer[((xc + 0) * zSize + (zc + 0)) * ySize + (yc + 1)] - s0) * yStep; 63 double s1a = (buffer[((xc + 0) * zSize + (zc + 1)) * ySize + (yc + 1)] - s1) * yStep; 64 double s2a = (buffer[((xc + 1) * zSize + (zc + 0)) * ySize + (yc + 1)] - s2) * yStep; 65 double s3a = (buffer[((xc + 1) * zSize + (zc + 1)) * ySize + (yc + 1)] - s3) * yStep; 66 67 for (int y = 0; y < CHUNK_HEIGHT; y++) 68 { 69 double xStep = 1 / (double) CHUNK_WIDTH; 70 71 double _s0 = s0; 72 double _s1 = s1; 73 double _s0a = (s2 - s0) * xStep; 74 double _s1a = (s3 - s1) * xStep; 75 76 for (int x = 0; x < CHUNK_WIDTH; x++) 77 { 78 int offs = (x + xc * CHUNK_WIDTH) << Level::genDepthBitsPlusFour | (0 + zc * CHUNK_WIDTH) << Level::genDepthBits | (yc * CHUNK_HEIGHT + y); 79 int step = 1 << Level::genDepthBits; 80 double zStep = 1 / (double) CHUNK_WIDTH; 81 82 double val = _s0; 83 double vala = (_s1 - _s0) * zStep; 84 for (int z = 0; z < CHUNK_WIDTH; z++) 85 { 86 int tileId = 0; 87 if (val > 0) 88 { 89 tileId = Tile::endStone_Id; 90 } else { 91 } 92 93 blocks[offs] = (byte) tileId; 94 offs += step; 95 val += vala; 96 } 97 _s0 += _s0a; 98 _s1 += _s1a; 99 } 100 101 s0 += s0a; 102 s1 += s1a; 103 s2 += s2a; 104 s3 += s3a; 105 } 106 } 107 } 108 } 109 delete [] buffer.data; 110 111} 112 113void TheEndLevelRandomLevelSource::buildSurfaces(int xOffs, int zOffs, byteArray blocks, BiomeArray biomes) 114{ 115 for (int x = 0; x < 16; x++) 116 { 117 for (int z = 0; z < 16; z++) 118 { 119 int runDepth = 1; 120 int run = -1; 121 122 byte top = (byte) Tile::endStone_Id; 123 byte material = (byte) Tile::endStone_Id; 124 125 for (int y = Level::genDepthMinusOne; y >= 0; y--) 126 { 127 int offs = (z * 16 + x) * Level::genDepth + y; 128 129 int old = blocks[offs]; 130 131 if (old == 0) 132 { 133 run = -1; 134 } 135 else if (old == Tile::stone_Id) 136 { 137 if (run == -1) 138 { 139 if (runDepth <= 0) 140 { 141 top = 0; 142 material = (byte) Tile::endStone_Id; 143 } 144 145 run = runDepth; 146 if (y >= 0) blocks[offs] = top; 147 else blocks[offs] = material; 148 } 149 else if (run > 0) 150 { 151 run--; 152 blocks[offs] = material; 153 } 154 } 155 } 156 } 157 } 158} 159 160LevelChunk *TheEndLevelRandomLevelSource::create(int x, int z) 161{ 162 return getChunk(x, z); 163} 164 165LevelChunk *TheEndLevelRandomLevelSource::getChunk(int xOffs, int zOffs) 166{ 167 random->setSeed(xOffs * 341873128712l + zOffs * 132897987541l); 168 169 BiomeArray biomes; 170 // 4J - now allocating this with a physical alloc & bypassing general memory management so that it will get cleanly freed 171 unsigned int blocksSize = Level::genDepth * 16 * 16; 172 byte *tileData = (byte *)XPhysicalAlloc(blocksSize, MAXULONG_PTR, 4096, PAGE_READWRITE); 173 XMemSet128(tileData,0,blocksSize); 174 byteArray blocks = byteArray(tileData,blocksSize); 175 // byteArray blocks = byteArray(16 * level->depth * 16); 176 177 // LevelChunk *levelChunk = new LevelChunk(level, blocks, xOffs, zOffs); // 4J moved below 178 level->getBiomeSource()->getBiomeBlock(biomes, xOffs * 16, zOffs * 16, 16, 16, true); 179 180 prepareHeights(xOffs, zOffs, blocks, biomes); 181 buildSurfaces(xOffs, zOffs, blocks, biomes); 182 183 // 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 184 // now need to free the passed in blocks as the LevelChunk doesn't use the passed in allocation anymore. 185 LevelChunk *levelChunk = new LevelChunk(level, blocks, xOffs, zOffs); 186 XPhysicalFree(tileData); 187 188 levelChunk->recalcHeightmap(); 189 190 //delete blocks.data; // Don't delete the blocks as the array data is actually owned by the chunk now 191 delete biomes.data; 192 193 return levelChunk; 194} 195 196doubleArray TheEndLevelRandomLevelSource::getHeights(doubleArray buffer, int x, int y, int z, int xSize, int ySize, int zSize) 197{ 198 if (buffer.data == NULL) 199 { 200 buffer = doubleArray(xSize * ySize * zSize); 201 } 202 203 double s = 1 * 684.412; 204 double hs = 1 * 684.412; 205 206 doubleArray pnr, ar, br, sr, dr, fi, fis; // 4J - used to be declared with class level scope but moved here for thread safety 207 208 sr = scaleNoise->getRegion(sr, x, z, xSize, zSize, 1.121, 1.121, 0.5); 209 dr = depthNoise->getRegion(dr, x, z, xSize, zSize, 200.0, 200.0, 0.5); 210 211 s *= 2; 212 213 pnr = perlinNoise1->getRegion(pnr, x, y, z, xSize, ySize, zSize, s / 80.0, hs / 160.0, s / 80.0); 214 ar = lperlinNoise1->getRegion(ar, x, y, z, xSize, ySize, zSize, s, hs, s); 215 br = lperlinNoise2->getRegion(br, x, y, z, xSize, ySize, zSize, s, hs, s); 216 217 int p = 0; 218 int pp = 0; 219 220 for (int xx = 0; xx < xSize; xx++) 221 { 222 for (int zz = 0; zz < zSize; zz++) 223 { 224 double scale = ((sr[pp] + 256.0) / 512); 225 if (scale > 1) scale = 1; 226 227 228 double depth = (dr[pp] / 8000.0); 229 if (depth < 0) depth = -depth * 0.3; 230 depth = depth * 3.0 - 2.0; 231 232 float xd = ((xx + x) - 0) / 1.0f; 233 float zd = ((zz + z) - 0) / 1.0f; 234 float doffs = 100 - sqrt(xd * xd + zd * zd) * 8; 235 if (doffs > 80) doffs = 80; 236 if (doffs < -100) doffs = -100; 237 if (depth > 1) depth = 1; 238 depth = depth / 8; 239 depth = 0; 240 241 if (scale < 0) scale = 0; 242 scale = (scale) + 0.5; 243 depth = depth * ySize / 16; 244 245 pp++; 246 247 double yCenter = ySize / 2.0; 248 249 250 for (int yy = 0; yy < ySize; yy++) 251 { 252 double val = 0; 253 double yOffs = (yy - (yCenter)) * 8 / scale; 254 255 if (yOffs < 0) yOffs *= -1; 256 257 double bb = ar[p] / 512; 258 double cc = br[p] / 512; 259 260 double v = (pnr[p] / 10 + 1) / 2; 261 if (v < 0) val = bb; 262 else if (v > 1) val = cc; 263 else val = bb + (cc - bb) * v; 264 val -= 8; 265 val += doffs; 266 267 int r = 2; 268 if (yy > ySize / 2 - r) 269 { 270 double slide = (yy - (ySize / 2 - r)) / (64.0f); 271 if (slide < 0) slide = 0; 272 if (slide > 1) slide = 1; 273 val = val * (1 - slide) + -3000 * slide; 274 } 275 r = 8; 276 if (yy < r) 277 { 278 double slide = (r - yy) / (r - 1.0f); 279 val = val * (1 - slide) + -30 * slide; 280 } 281 282 283 buffer[p] = val; 284 p++; 285 } 286 } 287 } 288 289 delete [] pnr.data; 290 delete [] ar.data; 291 delete [] br.data; 292 delete [] sr.data; 293 delete [] dr.data; 294 delete [] fi.data; 295 delete [] fis.data; 296 297 return buffer; 298 299} 300 301bool TheEndLevelRandomLevelSource::hasChunk(int x, int y) 302{ 303 return true; 304} 305 306void TheEndLevelRandomLevelSource::calcWaterDepths(ChunkSource *parent, int xt, int zt) 307{ 308 int xo = xt * 16; 309 int zo = zt * 16; 310 for (int x = 0; x < 16; x++) 311 { 312 int y = level->getSeaLevel(); 313 for (int z = 0; z < 16; z++) 314 { 315 int xp = xo + x + 7; 316 int zp = zo + z + 7; 317 int h = level->getHeightmap(xp, zp); 318 if (h <= 0) 319 { 320 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) 321 { 322 bool hadWater = false; 323 if (hadWater || (level->getTile(xp - 1, y, zp) == Tile::calmWater_Id && level->getData(xp - 1, y, zp) < 7)) hadWater = true; 324 if (hadWater || (level->getTile(xp + 1, y, zp) == Tile::calmWater_Id && level->getData(xp + 1, y, zp) < 7)) hadWater = true; 325 if (hadWater || (level->getTile(xp, y, zp - 1) == Tile::calmWater_Id && level->getData(xp, y, zp - 1) < 7)) hadWater = true; 326 if (hadWater || (level->getTile(xp, y, zp + 1) == Tile::calmWater_Id && level->getData(xp, y, zp + 1) < 7)) hadWater = true; 327 if (hadWater) 328 { 329 for (int x2 = -5; x2 <= 5; x2++) 330 { 331 for (int z2 = -5; z2 <= 5; z2++) 332 { 333 int d = (x2 > 0 ? x2 : -x2) + (z2 > 0 ? z2 : -z2); 334 335 if (d <= 5) 336 { 337 d = 6 - d; 338 if (level->getTile(xp + x2, y, zp + z2) == Tile::calmWater_Id) 339 { 340 int od = level->getData(xp + x2, y, zp + z2); 341 if (od < 7 && od < d) 342 { 343 level->setData(xp + x2, y, zp + z2, d, Tile::UPDATE_CLIENTS); 344 } 345 } 346 } 347 } 348 } 349 if (hadWater) 350 { 351 level->setTileAndData(xp, y, zp, Tile::calmWater_Id, 7, Tile::UPDATE_CLIENTS); 352 for (int y2 = 0; y2 < y; y2++) 353 { 354 level->setTileAndData(xp, y2, zp, Tile::calmWater_Id, 8, Tile::UPDATE_CLIENTS); 355 } 356 } 357 } 358 } 359 } 360 } 361 } 362 363} 364 365void TheEndLevelRandomLevelSource::postProcess(ChunkSource *parent, int xt, int zt) 366{ 367 HeavyTile::instaFall = true; 368 int xo = xt * 16; 369 int zo = zt * 16; 370 371 // 4J - added. The original java didn't do any setting of the random seed here, and passes the level random to the biome decorator. 372 // We'll be running our postProcess in parallel with getChunk etc. so we need to use a separate random - have used the same initialisation code as 373 // used in RandomLevelSource::postProcess to make sure this random value is consistent for each world generation. 374 pprandom->setSeed(level->getSeed()); 375 __int64 xScale = pprandom->nextLong() / 2 * 2 + 1; 376 __int64 zScale = pprandom->nextLong() / 2 * 2 + 1; 377 pprandom->setSeed(((xt * xScale) + (zt * zScale)) ^ level->getSeed()); 378 379 Biome *biome = level->getBiome(xo + 16, zo + 16); 380 biome->decorate(level, pprandom, xo, zo); // 4J - passing pprandom rather than level->random here to make this consistent with our parallel world generation 381 382 HeavyTile::instaFall = false; 383 384 app.processSchematics(parent->getChunk(xt,zt)); 385} 386 387bool TheEndLevelRandomLevelSource::save(bool force, ProgressListener *progressListener) 388{ 389 return true; 390} 391 392bool TheEndLevelRandomLevelSource::tick() 393{ 394 return false; 395} 396 397bool TheEndLevelRandomLevelSource::shouldSave() 398{ 399 return true; 400} 401 402wstring TheEndLevelRandomLevelSource::gatherStats() 403{ 404 return L"RandomLevelSource"; 405} 406 407vector<Biome::MobSpawnerData *> *TheEndLevelRandomLevelSource::getMobsAt(MobCategory *mobCategory, int x, int y, int z) 408{ 409 Biome *biome = level->getBiome(x, z); 410 if (biome == NULL) 411 { 412 return NULL; 413 } 414 return biome->getMobs(mobCategory); 415} 416 417TilePos *TheEndLevelRandomLevelSource::findNearestMapFeature(Level *level, const wstring& featureName, int x, int y, int z) 418{ 419 return NULL; 420} 421 422void TheEndLevelRandomLevelSource::recreateLogicStructuresForChunk(int chunkX, int chunkZ) 423{ 424}