001package net.minecraft.world.gen; 002 003import java.util.List; 004import java.util.Random; 005import net.minecraft.block.Block; 006import net.minecraft.block.BlockSand; 007import net.minecraft.entity.EnumCreatureType; 008import net.minecraft.util.IProgressUpdate; 009import net.minecraft.util.MathHelper; 010import net.minecraft.world.ChunkPosition; 011import net.minecraft.world.SpawnerAnimals; 012import net.minecraft.world.World; 013import net.minecraft.world.biome.BiomeGenBase; 014import net.minecraft.world.chunk.Chunk; 015import net.minecraft.world.chunk.IChunkProvider; 016import net.minecraft.world.gen.feature.MapGenScatteredFeature; 017import net.minecraft.world.gen.feature.WorldGenDungeons; 018import net.minecraft.world.gen.feature.WorldGenLakes; 019import net.minecraft.world.gen.structure.MapGenMineshaft; 020import net.minecraft.world.gen.structure.MapGenStronghold; 021import net.minecraft.world.gen.structure.MapGenVillage; 022 023import static net.minecraftforge.event.terraingen.InitMapGenEvent.EventType.*; 024import static net.minecraftforge.event.terraingen.PopulateChunkEvent.Populate.EventType.*; 025import net.minecraftforge.common.*; 026import net.minecraftforge.event.Event.*; 027import net.minecraftforge.event.terraingen.*; 028 029public class ChunkProviderGenerate implements IChunkProvider 030{ 031 /** RNG. */ 032 private Random rand; 033 034 /** A NoiseGeneratorOctaves used in generating terrain */ 035 private NoiseGeneratorOctaves noiseGen1; 036 037 /** A NoiseGeneratorOctaves used in generating terrain */ 038 private NoiseGeneratorOctaves noiseGen2; 039 040 /** A NoiseGeneratorOctaves used in generating terrain */ 041 private NoiseGeneratorOctaves noiseGen3; 042 043 /** A NoiseGeneratorOctaves used in generating terrain */ 044 private NoiseGeneratorOctaves noiseGen4; 045 046 /** A NoiseGeneratorOctaves used in generating terrain */ 047 public NoiseGeneratorOctaves noiseGen5; 048 049 /** A NoiseGeneratorOctaves used in generating terrain */ 050 public NoiseGeneratorOctaves noiseGen6; 051 public NoiseGeneratorOctaves mobSpawnerNoise; 052 053 /** Reference to the World object. */ 054 private World worldObj; 055 056 /** are map structures going to be generated (e.g. strongholds) */ 057 private final boolean mapFeaturesEnabled; 058 059 /** Holds the overall noise array used in chunk generation */ 060 private double[] noiseArray; 061 private double[] stoneNoise = new double[256]; 062 private MapGenBase caveGenerator = new MapGenCaves(); 063 064 /** Holds Stronghold Generator */ 065 private MapGenStronghold strongholdGenerator = new MapGenStronghold(); 066 067 /** Holds Village Generator */ 068 private MapGenVillage villageGenerator = new MapGenVillage(); 069 070 /** Holds Mineshaft Generator */ 071 private MapGenMineshaft mineshaftGenerator = new MapGenMineshaft(); 072 private MapGenScatteredFeature scatteredFeatureGenerator = new MapGenScatteredFeature(); 073 074 /** Holds ravine generator */ 075 private MapGenBase ravineGenerator = new MapGenRavine(); 076 077 /** The biomes that are used to generate the chunk */ 078 private BiomeGenBase[] biomesForGeneration; 079 080 /** A double array that hold terrain noise from noiseGen3 */ 081 double[] noise3; 082 083 /** A double array that hold terrain noise */ 084 double[] noise1; 085 086 /** A double array that hold terrain noise from noiseGen2 */ 087 double[] noise2; 088 089 /** A double array that hold terrain noise from noiseGen5 */ 090 double[] noise5; 091 092 /** A double array that holds terrain noise from noiseGen6 */ 093 double[] noise6; 094 095 /** 096 * Used to store the 5x5 parabolic field that is used during terrain generation. 097 */ 098 float[] parabolicField; 099 int[][] field_73219_j = new int[32][32]; 100 101 { 102 caveGenerator = TerrainGen.getModdedMapGen(caveGenerator, CAVE); 103 strongholdGenerator = (MapGenStronghold) TerrainGen.getModdedMapGen(strongholdGenerator, STRONGHOLD); 104 villageGenerator = (MapGenVillage) TerrainGen.getModdedMapGen(villageGenerator, VILLAGE); 105 mineshaftGenerator = (MapGenMineshaft) TerrainGen.getModdedMapGen(mineshaftGenerator, MINESHAFT); 106 scatteredFeatureGenerator = (MapGenScatteredFeature) TerrainGen.getModdedMapGen(scatteredFeatureGenerator, SCATTERED_FEATURE); 107 ravineGenerator = TerrainGen.getModdedMapGen(ravineGenerator, RAVINE); 108 } 109 110 public ChunkProviderGenerate(World par1World, long par2, boolean par4) 111 { 112 this.worldObj = par1World; 113 this.mapFeaturesEnabled = par4; 114 this.rand = new Random(par2); 115 this.noiseGen1 = new NoiseGeneratorOctaves(this.rand, 16); 116 this.noiseGen2 = new NoiseGeneratorOctaves(this.rand, 16); 117 this.noiseGen3 = new NoiseGeneratorOctaves(this.rand, 8); 118 this.noiseGen4 = new NoiseGeneratorOctaves(this.rand, 4); 119 this.noiseGen5 = new NoiseGeneratorOctaves(this.rand, 10); 120 this.noiseGen6 = new NoiseGeneratorOctaves(this.rand, 16); 121 this.mobSpawnerNoise = new NoiseGeneratorOctaves(this.rand, 8); 122 123 NoiseGeneratorOctaves[] noiseGens = {noiseGen1, noiseGen2, noiseGen3, noiseGen4, noiseGen5, noiseGen6, mobSpawnerNoise}; 124 noiseGens = TerrainGen.getModdedNoiseGenerators(par1World, this.rand, noiseGens); 125 this.noiseGen1 = noiseGens[0]; 126 this.noiseGen2 = noiseGens[1]; 127 this.noiseGen3 = noiseGens[2]; 128 this.noiseGen4 = noiseGens[3]; 129 this.noiseGen5 = noiseGens[4]; 130 this.noiseGen6 = noiseGens[5]; 131 this.mobSpawnerNoise = noiseGens[6]; 132 } 133 134 /** 135 * Generates the shape of the terrain for the chunk though its all stone though the water is frozen if the 136 * temperature is low enough 137 */ 138 public void generateTerrain(int par1, int par2, byte[] par3ArrayOfByte) 139 { 140 byte b0 = 4; 141 byte b1 = 16; 142 byte b2 = 63; 143 int k = b0 + 1; 144 byte b3 = 17; 145 int l = b0 + 1; 146 this.biomesForGeneration = this.worldObj.getWorldChunkManager().getBiomesForGeneration(this.biomesForGeneration, par1 * 4 - 2, par2 * 4 - 2, k + 5, l + 5); 147 this.noiseArray = this.initializeNoiseField(this.noiseArray, par1 * b0, 0, par2 * b0, k, b3, l); 148 149 for (int i1 = 0; i1 < b0; ++i1) 150 { 151 for (int j1 = 0; j1 < b0; ++j1) 152 { 153 for (int k1 = 0; k1 < b1; ++k1) 154 { 155 double d0 = 0.125D; 156 double d1 = this.noiseArray[((i1 + 0) * l + j1 + 0) * b3 + k1 + 0]; 157 double d2 = this.noiseArray[((i1 + 0) * l + j1 + 1) * b3 + k1 + 0]; 158 double d3 = this.noiseArray[((i1 + 1) * l + j1 + 0) * b3 + k1 + 0]; 159 double d4 = this.noiseArray[((i1 + 1) * l + j1 + 1) * b3 + k1 + 0]; 160 double d5 = (this.noiseArray[((i1 + 0) * l + j1 + 0) * b3 + k1 + 1] - d1) * d0; 161 double d6 = (this.noiseArray[((i1 + 0) * l + j1 + 1) * b3 + k1 + 1] - d2) * d0; 162 double d7 = (this.noiseArray[((i1 + 1) * l + j1 + 0) * b3 + k1 + 1] - d3) * d0; 163 double d8 = (this.noiseArray[((i1 + 1) * l + j1 + 1) * b3 + k1 + 1] - d4) * d0; 164 165 for (int l1 = 0; l1 < 8; ++l1) 166 { 167 double d9 = 0.25D; 168 double d10 = d1; 169 double d11 = d2; 170 double d12 = (d3 - d1) * d9; 171 double d13 = (d4 - d2) * d9; 172 173 for (int i2 = 0; i2 < 4; ++i2) 174 { 175 int j2 = i2 + i1 * 4 << 11 | 0 + j1 * 4 << 7 | k1 * 8 + l1; 176 short short1 = 128; 177 j2 -= short1; 178 double d14 = 0.25D; 179 double d15 = (d11 - d10) * d14; 180 double d16 = d10 - d15; 181 182 for (int k2 = 0; k2 < 4; ++k2) 183 { 184 if ((d16 += d15) > 0.0D) 185 { 186 par3ArrayOfByte[j2 += short1] = (byte)Block.stone.blockID; 187 } 188 else if (k1 * 8 + l1 < b2) 189 { 190 par3ArrayOfByte[j2 += short1] = (byte)Block.waterStill.blockID; 191 } 192 else 193 { 194 par3ArrayOfByte[j2 += short1] = 0; 195 } 196 } 197 198 d10 += d12; 199 d11 += d13; 200 } 201 202 d1 += d5; 203 d2 += d6; 204 d3 += d7; 205 d4 += d8; 206 } 207 } 208 } 209 } 210 } 211 212 /** 213 * Replaces the stone that was placed in with blocks that match the biome 214 */ 215 public void replaceBlocksForBiome(int par1, int par2, byte[] par3ArrayOfByte, BiomeGenBase[] par4ArrayOfBiomeGenBase) 216 { 217 ChunkProviderEvent.ReplaceBiomeBlocks event = new ChunkProviderEvent.ReplaceBiomeBlocks(this, par1, par2, par3ArrayOfByte, par4ArrayOfBiomeGenBase); 218 MinecraftForge.EVENT_BUS.post(event); 219 if (event.getResult() == Result.DENY) return; 220 221 byte b0 = 63; 222 double d0 = 0.03125D; 223 this.stoneNoise = this.noiseGen4.generateNoiseOctaves(this.stoneNoise, par1 * 16, par2 * 16, 0, 16, 16, 1, d0 * 2.0D, d0 * 2.0D, d0 * 2.0D); 224 225 for (int k = 0; k < 16; ++k) 226 { 227 for (int l = 0; l < 16; ++l) 228 { 229 BiomeGenBase biomegenbase = par4ArrayOfBiomeGenBase[l + k * 16]; 230 float f = biomegenbase.getFloatTemperature(); 231 int i1 = (int)(this.stoneNoise[k + l * 16] / 3.0D + 3.0D + this.rand.nextDouble() * 0.25D); 232 int j1 = -1; 233 byte b1 = biomegenbase.topBlock; 234 byte b2 = biomegenbase.fillerBlock; 235 236 for (int k1 = 127; k1 >= 0; --k1) 237 { 238 int l1 = (l * 16 + k) * 128 + k1; 239 240 if (k1 <= 0 + this.rand.nextInt(5)) 241 { 242 par3ArrayOfByte[l1] = (byte)Block.bedrock.blockID; 243 } 244 else 245 { 246 byte b3 = par3ArrayOfByte[l1]; 247 248 if (b3 == 0) 249 { 250 j1 = -1; 251 } 252 else if (b3 == Block.stone.blockID) 253 { 254 if (j1 == -1) 255 { 256 if (i1 <= 0) 257 { 258 b1 = 0; 259 b2 = (byte)Block.stone.blockID; 260 } 261 else if (k1 >= b0 - 4 && k1 <= b0 + 1) 262 { 263 b1 = biomegenbase.topBlock; 264 b2 = biomegenbase.fillerBlock; 265 } 266 267 if (k1 < b0 && b1 == 0) 268 { 269 if (f < 0.15F) 270 { 271 b1 = (byte)Block.ice.blockID; 272 } 273 else 274 { 275 b1 = (byte)Block.waterStill.blockID; 276 } 277 } 278 279 j1 = i1; 280 281 if (k1 >= b0 - 1) 282 { 283 par3ArrayOfByte[l1] = b1; 284 } 285 else 286 { 287 par3ArrayOfByte[l1] = b2; 288 } 289 } 290 else if (j1 > 0) 291 { 292 --j1; 293 par3ArrayOfByte[l1] = b2; 294 295 if (j1 == 0 && b2 == Block.sand.blockID) 296 { 297 j1 = this.rand.nextInt(4); 298 b2 = (byte)Block.sandStone.blockID; 299 } 300 } 301 } 302 } 303 } 304 } 305 } 306 } 307 308 /** 309 * loads or generates the chunk at the chunk location specified 310 */ 311 public Chunk loadChunk(int par1, int par2) 312 { 313 return this.provideChunk(par1, par2); 314 } 315 316 /** 317 * Will return back a chunk, if it doesn't exist and its not a MP client it will generates all the blocks for the 318 * specified chunk from the map seed and chunk seed 319 */ 320 public Chunk provideChunk(int par1, int par2) 321 { 322 this.rand.setSeed((long)par1 * 341873128712L + (long)par2 * 132897987541L); 323 byte[] abyte = new byte[32768]; 324 this.generateTerrain(par1, par2, abyte); 325 this.biomesForGeneration = this.worldObj.getWorldChunkManager().loadBlockGeneratorData(this.biomesForGeneration, par1 * 16, par2 * 16, 16, 16); 326 this.replaceBlocksForBiome(par1, par2, abyte, this.biomesForGeneration); 327 this.caveGenerator.generate(this, this.worldObj, par1, par2, abyte); 328 this.ravineGenerator.generate(this, this.worldObj, par1, par2, abyte); 329 330 if (this.mapFeaturesEnabled) 331 { 332 this.mineshaftGenerator.generate(this, this.worldObj, par1, par2, abyte); 333 this.villageGenerator.generate(this, this.worldObj, par1, par2, abyte); 334 this.strongholdGenerator.generate(this, this.worldObj, par1, par2, abyte); 335 this.scatteredFeatureGenerator.generate(this, this.worldObj, par1, par2, abyte); 336 } 337 338 Chunk chunk = new Chunk(this.worldObj, abyte, par1, par2); 339 byte[] abyte1 = chunk.getBiomeArray(); 340 341 for (int k = 0; k < abyte1.length; ++k) 342 { 343 abyte1[k] = (byte)this.biomesForGeneration[k].biomeID; 344 } 345 346 chunk.generateSkylightMap(); 347 return chunk; 348 } 349 350 /** 351 * generates a subset of the level's terrain data. Takes 7 arguments: the [empty] noise array, the position, and the 352 * size. 353 */ 354 private double[] initializeNoiseField(double[] par1ArrayOfDouble, int par2, int par3, int par4, int par5, int par6, int par7) 355 { 356 ChunkProviderEvent.InitNoiseField event = new ChunkProviderEvent.InitNoiseField(this, par1ArrayOfDouble, par2, par3, par4, par5, par6, par7); 357 MinecraftForge.EVENT_BUS.post(event); 358 if (event.getResult() == Result.DENY) return event.noisefield; 359 360 if (par1ArrayOfDouble == null) 361 { 362 par1ArrayOfDouble = new double[par5 * par6 * par7]; 363 } 364 365 if (this.parabolicField == null) 366 { 367 this.parabolicField = new float[25]; 368 369 for (int k1 = -2; k1 <= 2; ++k1) 370 { 371 for (int l1 = -2; l1 <= 2; ++l1) 372 { 373 float f = 10.0F / MathHelper.sqrt_float((float)(k1 * k1 + l1 * l1) + 0.2F); 374 this.parabolicField[k1 + 2 + (l1 + 2) * 5] = f; 375 } 376 } 377 } 378 379 double d0 = 684.412D; 380 double d1 = 684.412D; 381 this.noise5 = this.noiseGen5.generateNoiseOctaves(this.noise5, par2, par4, par5, par7, 1.121D, 1.121D, 0.5D); 382 this.noise6 = this.noiseGen6.generateNoiseOctaves(this.noise6, par2, par4, par5, par7, 200.0D, 200.0D, 0.5D); 383 this.noise3 = this.noiseGen3.generateNoiseOctaves(this.noise3, par2, par3, par4, par5, par6, par7, d0 / 80.0D, d1 / 160.0D, d0 / 80.0D); 384 this.noise1 = this.noiseGen1.generateNoiseOctaves(this.noise1, par2, par3, par4, par5, par6, par7, d0, d1, d0); 385 this.noise2 = this.noiseGen2.generateNoiseOctaves(this.noise2, par2, par3, par4, par5, par6, par7, d0, d1, d0); 386 boolean flag = false; 387 boolean flag1 = false; 388 int i2 = 0; 389 int j2 = 0; 390 391 for (int k2 = 0; k2 < par5; ++k2) 392 { 393 for (int l2 = 0; l2 < par7; ++l2) 394 { 395 float f1 = 0.0F; 396 float f2 = 0.0F; 397 float f3 = 0.0F; 398 byte b0 = 2; 399 BiomeGenBase biomegenbase = this.biomesForGeneration[k2 + 2 + (l2 + 2) * (par5 + 5)]; 400 401 for (int i3 = -b0; i3 <= b0; ++i3) 402 { 403 for (int j3 = -b0; j3 <= b0; ++j3) 404 { 405 BiomeGenBase biomegenbase1 = this.biomesForGeneration[k2 + i3 + 2 + (l2 + j3 + 2) * (par5 + 5)]; 406 float f4 = this.parabolicField[i3 + 2 + (j3 + 2) * 5] / (biomegenbase1.minHeight + 2.0F); 407 408 if (biomegenbase1.minHeight > biomegenbase.minHeight) 409 { 410 f4 /= 2.0F; 411 } 412 413 f1 += biomegenbase1.maxHeight * f4; 414 f2 += biomegenbase1.minHeight * f4; 415 f3 += f4; 416 } 417 } 418 419 f1 /= f3; 420 f2 /= f3; 421 f1 = f1 * 0.9F + 0.1F; 422 f2 = (f2 * 4.0F - 1.0F) / 8.0F; 423 double d2 = this.noise6[j2] / 8000.0D; 424 425 if (d2 < 0.0D) 426 { 427 d2 = -d2 * 0.3D; 428 } 429 430 d2 = d2 * 3.0D - 2.0D; 431 432 if (d2 < 0.0D) 433 { 434 d2 /= 2.0D; 435 436 if (d2 < -1.0D) 437 { 438 d2 = -1.0D; 439 } 440 441 d2 /= 1.4D; 442 d2 /= 2.0D; 443 } 444 else 445 { 446 if (d2 > 1.0D) 447 { 448 d2 = 1.0D; 449 } 450 451 d2 /= 8.0D; 452 } 453 454 ++j2; 455 456 for (int k3 = 0; k3 < par6; ++k3) 457 { 458 double d3 = (double)f2; 459 double d4 = (double)f1; 460 d3 += d2 * 0.2D; 461 d3 = d3 * (double)par6 / 16.0D; 462 double d5 = (double)par6 / 2.0D + d3 * 4.0D; 463 double d6 = 0.0D; 464 double d7 = ((double)k3 - d5) * 12.0D * 128.0D / 128.0D / d4; 465 466 if (d7 < 0.0D) 467 { 468 d7 *= 4.0D; 469 } 470 471 double d8 = this.noise1[i2] / 512.0D; 472 double d9 = this.noise2[i2] / 512.0D; 473 double d10 = (this.noise3[i2] / 10.0D + 1.0D) / 2.0D; 474 475 if (d10 < 0.0D) 476 { 477 d6 = d8; 478 } 479 else if (d10 > 1.0D) 480 { 481 d6 = d9; 482 } 483 else 484 { 485 d6 = d8 + (d9 - d8) * d10; 486 } 487 488 d6 -= d7; 489 490 if (k3 > par6 - 4) 491 { 492 double d11 = (double)((float)(k3 - (par6 - 4)) / 3.0F); 493 d6 = d6 * (1.0D - d11) + -10.0D * d11; 494 } 495 496 par1ArrayOfDouble[i2] = d6; 497 ++i2; 498 } 499 } 500 } 501 502 return par1ArrayOfDouble; 503 } 504 505 /** 506 * Checks to see if a chunk exists at x, y 507 */ 508 public boolean chunkExists(int par1, int par2) 509 { 510 return true; 511 } 512 513 /** 514 * Populates chunk with ores etc etc 515 */ 516 public void populate(IChunkProvider par1IChunkProvider, int par2, int par3) 517 { 518 BlockSand.fallInstantly = true; 519 int k = par2 * 16; 520 int l = par3 * 16; 521 BiomeGenBase biomegenbase = this.worldObj.getBiomeGenForCoords(k + 16, l + 16); 522 this.rand.setSeed(this.worldObj.getSeed()); 523 long i1 = this.rand.nextLong() / 2L * 2L + 1L; 524 long j1 = this.rand.nextLong() / 2L * 2L + 1L; 525 this.rand.setSeed((long)par2 * i1 + (long)par3 * j1 ^ this.worldObj.getSeed()); 526 boolean flag = false; 527 528 MinecraftForge.EVENT_BUS.post(new PopulateChunkEvent.Pre(par1IChunkProvider, worldObj, rand, par2, par3, flag)); 529 530 if (this.mapFeaturesEnabled) 531 { 532 this.mineshaftGenerator.generateStructuresInChunk(this.worldObj, this.rand, par2, par3); 533 flag = this.villageGenerator.generateStructuresInChunk(this.worldObj, this.rand, par2, par3); 534 this.strongholdGenerator.generateStructuresInChunk(this.worldObj, this.rand, par2, par3); 535 this.scatteredFeatureGenerator.generateStructuresInChunk(this.worldObj, this.rand, par2, par3); 536 } 537 538 int k1; 539 int l1; 540 int i2; 541 542 if (TerrainGen.populate(par1IChunkProvider, worldObj, rand, par2, par3, flag, LAKE) && 543 !flag && this.rand.nextInt(4) == 0) 544 { 545 k1 = k + this.rand.nextInt(16) + 8; 546 l1 = this.rand.nextInt(128); 547 i2 = l + this.rand.nextInt(16) + 8; 548 (new WorldGenLakes(Block.waterStill.blockID)).generate(this.worldObj, this.rand, k1, l1, i2); 549 } 550 551 if (TerrainGen.populate(par1IChunkProvider, worldObj, rand, par2, par3, flag, LAVA) && 552 !flag && this.rand.nextInt(8) == 0) 553 { 554 k1 = k + this.rand.nextInt(16) + 8; 555 l1 = this.rand.nextInt(this.rand.nextInt(120) + 8); 556 i2 = l + this.rand.nextInt(16) + 8; 557 558 if (l1 < 63 || this.rand.nextInt(10) == 0) 559 { 560 (new WorldGenLakes(Block.lavaStill.blockID)).generate(this.worldObj, this.rand, k1, l1, i2); 561 } 562 } 563 564 boolean doGen = TerrainGen.populate(par1IChunkProvider, worldObj, rand, par2, par3, flag, DUNGEON); 565 for (k1 = 0; doGen && k1 < 8; ++k1) 566 { 567 l1 = k + this.rand.nextInt(16) + 8; 568 i2 = this.rand.nextInt(128); 569 int j2 = l + this.rand.nextInt(16) + 8; 570 571 if ((new WorldGenDungeons()).generate(this.worldObj, this.rand, l1, i2, j2)) 572 { 573 ; 574 } 575 } 576 577 biomegenbase.decorate(this.worldObj, this.rand, k, l); 578 SpawnerAnimals.performWorldGenSpawning(this.worldObj, biomegenbase, k + 8, l + 8, 16, 16, this.rand); 579 k += 8; 580 l += 8; 581 582 doGen = TerrainGen.populate(par1IChunkProvider, worldObj, rand, par2, par3, flag, ICE); 583 for (k1 = 0; doGen && k1 < 16; ++k1) 584 { 585 for (l1 = 0; l1 < 16; ++l1) 586 { 587 i2 = this.worldObj.getPrecipitationHeight(k + k1, l + l1); 588 589 if (this.worldObj.isBlockFreezable(k1 + k, i2 - 1, l1 + l)) 590 { 591 this.worldObj.setBlock(k1 + k, i2 - 1, l1 + l, Block.ice.blockID, 0, 2); 592 } 593 594 if (this.worldObj.canSnowAt(k1 + k, i2, l1 + l)) 595 { 596 this.worldObj.setBlock(k1 + k, i2, l1 + l, Block.snow.blockID, 0, 2); 597 } 598 } 599 } 600 601 MinecraftForge.EVENT_BUS.post(new PopulateChunkEvent.Post(par1IChunkProvider, worldObj, rand, par2, par3, flag)); 602 603 BlockSand.fallInstantly = false; 604 } 605 606 /** 607 * Two modes of operation: if passed true, save all Chunks in one go. If passed false, save up to two chunks. 608 * Return true if all chunks have been saved. 609 */ 610 public boolean saveChunks(boolean par1, IProgressUpdate par2IProgressUpdate) 611 { 612 return true; 613 } 614 615 /** 616 * Unloads chunks that are marked to be unloaded. This is not guaranteed to unload every such chunk. 617 */ 618 public boolean unloadQueuedChunks() 619 { 620 return false; 621 } 622 623 /** 624 * Returns if the IChunkProvider supports saving. 625 */ 626 public boolean canSave() 627 { 628 return true; 629 } 630 631 /** 632 * Converts the instance data to a readable string. 633 */ 634 public String makeString() 635 { 636 return "RandomLevelSource"; 637 } 638 639 /** 640 * Returns a list of creatures of the specified type that can spawn at the given location. 641 */ 642 public List getPossibleCreatures(EnumCreatureType par1EnumCreatureType, int par2, int par3, int par4) 643 { 644 BiomeGenBase biomegenbase = this.worldObj.getBiomeGenForCoords(par2, par4); 645 return biomegenbase == null ? null : (biomegenbase == BiomeGenBase.swampland && par1EnumCreatureType == EnumCreatureType.monster && this.scatteredFeatureGenerator.hasStructureAt(par2, par3, par4) ? this.scatteredFeatureGenerator.getScatteredFeatureSpawnList() : biomegenbase.getSpawnableList(par1EnumCreatureType)); 646 } 647 648 /** 649 * Returns the location of the closest structure of the specified type. If not found returns null. 650 */ 651 public ChunkPosition findClosestStructure(World par1World, String par2Str, int par3, int par4, int par5) 652 { 653 return "Stronghold".equals(par2Str) && this.strongholdGenerator != null ? this.strongholdGenerator.getNearestInstance(par1World, par3, par4, par5) : null; 654 } 655 656 public int getLoadedChunkCount() 657 { 658 return 0; 659 } 660 661 public void recreateStructures(int par1, int par2) 662 { 663 if (this.mapFeaturesEnabled) 664 { 665 this.mineshaftGenerator.generate(this, this.worldObj, par1, par2, (byte[])null); 666 this.villageGenerator.generate(this, this.worldObj, par1, par2, (byte[])null); 667 this.strongholdGenerator.generate(this, this.worldObj, par1, par2, (byte[])null); 668 this.scatteredFeatureGenerator.generate(this, this.worldObj, par1, par2, (byte[])null); 669 } 670 } 671}