001 package net.minecraft.world.biome; 002 003 import java.util.Random; 004 import net.minecraft.block.Block; 005 import net.minecraft.world.World; 006 import net.minecraft.world.gen.feature.WorldGenBigMushroom; 007 import net.minecraft.world.gen.feature.WorldGenCactus; 008 import net.minecraft.world.gen.feature.WorldGenClay; 009 import net.minecraft.world.gen.feature.WorldGenDeadBush; 010 import net.minecraft.world.gen.feature.WorldGenFlowers; 011 import net.minecraft.world.gen.feature.WorldGenLiquids; 012 import net.minecraft.world.gen.feature.WorldGenMinable; 013 import net.minecraft.world.gen.feature.WorldGenPumpkin; 014 import net.minecraft.world.gen.feature.WorldGenReed; 015 import net.minecraft.world.gen.feature.WorldGenSand; 016 import net.minecraft.world.gen.feature.WorldGenWaterlily; 017 import net.minecraft.world.gen.feature.WorldGenerator; 018 019 import static net.minecraftforge.event.terraingen.DecorateBiomeEvent.Decorate.EventType.*; 020 import static net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.*; 021 import net.minecraftforge.common.*; 022 import net.minecraftforge.event.terraingen.*; 023 024 public class BiomeDecorator 025 { 026 /** The world the BiomeDecorator is currently decorating */ 027 public World currentWorld; 028 029 /** The Biome Decorator's random number generator. */ 030 public Random randomGenerator; 031 032 /** The X-coordinate of the chunk currently being decorated */ 033 public int chunk_X; 034 035 /** The Z-coordinate of the chunk currently being decorated */ 036 public int chunk_Z; 037 038 /** The biome generator object. */ 039 public BiomeGenBase biome; 040 041 /** The clay generator. */ 042 public WorldGenerator clayGen = new WorldGenClay(4); 043 044 /** The sand generator. */ 045 public WorldGenerator sandGen; 046 047 /** The gravel generator. */ 048 public WorldGenerator gravelAsSandGen; 049 050 /** The dirt generator. */ 051 public WorldGenerator dirtGen; 052 public WorldGenerator gravelGen; 053 public WorldGenerator coalGen; 054 public WorldGenerator ironGen; 055 056 /** Field that holds gold WorldGenMinable */ 057 public WorldGenerator goldGen; 058 059 /** Field that holds redstone WorldGenMinable */ 060 public WorldGenerator redstoneGen; 061 062 /** Field that holds diamond WorldGenMinable */ 063 public WorldGenerator diamondGen; 064 065 /** Field that holds Lapis WorldGenMinable */ 066 public WorldGenerator lapisGen; 067 068 /** Field that holds one of the plantYellow WorldGenFlowers */ 069 public WorldGenerator plantYellowGen; 070 071 /** Field that holds one of the plantRed WorldGenFlowers */ 072 public WorldGenerator plantRedGen; 073 074 /** Field that holds mushroomBrown WorldGenFlowers */ 075 public WorldGenerator mushroomBrownGen; 076 077 /** Field that holds mushroomRed WorldGenFlowers */ 078 public WorldGenerator mushroomRedGen; 079 080 /** Field that holds big mushroom generator */ 081 public WorldGenerator bigMushroomGen; 082 083 /** Field that holds WorldGenReed */ 084 public WorldGenerator reedGen; 085 086 /** Field that holds WorldGenCactus */ 087 public WorldGenerator cactusGen; 088 089 /** The water lily generation! */ 090 public WorldGenerator waterlilyGen; 091 092 /** Amount of waterlilys per chunk. */ 093 public int waterlilyPerChunk; 094 095 /** 096 * The number of trees to attempt to generate per chunk. Up to 10 in forests, none in deserts. 097 */ 098 public int treesPerChunk; 099 100 /** 101 * The number of yellow flower patches to generate per chunk. The game generates much less than this number, since 102 * it attempts to generate them at a random altitude. 103 */ 104 public int flowersPerChunk; 105 106 /** The amount of tall grass to generate per chunk. */ 107 public int grassPerChunk; 108 109 /** 110 * The number of dead bushes to generate per chunk. Used in deserts and swamps. 111 */ 112 public int deadBushPerChunk; 113 114 /** 115 * The number of extra mushroom patches per chunk. It generates 1/4 this number in brown mushroom patches, and 1/8 116 * this number in red mushroom patches. These mushrooms go beyond the default base number of mushrooms. 117 */ 118 public int mushroomsPerChunk; 119 120 /** 121 * The number of reeds to generate per chunk. Reeds won't generate if the randomly selected placement is unsuitable. 122 */ 123 public int reedsPerChunk; 124 125 /** 126 * The number of cactus plants to generate per chunk. Cacti only work on sand. 127 */ 128 public int cactiPerChunk; 129 130 /** 131 * The number of sand patches to generate per chunk. Sand patches only generate when part of it is underwater. 132 */ 133 public int sandPerChunk; 134 135 /** 136 * The number of sand patches to generate per chunk. Sand patches only generate when part of it is underwater. There 137 * appear to be two separate fields for this. 138 */ 139 public int sandPerChunk2; 140 141 /** 142 * The number of clay patches to generate per chunk. Only generates when part of it is underwater. 143 */ 144 public int clayPerChunk; 145 146 /** Amount of big mushrooms per chunk */ 147 public int bigMushroomsPerChunk; 148 149 /** True if decorator should generate surface lava & water */ 150 public boolean generateLakes; 151 152 public BiomeDecorator(BiomeGenBase par1BiomeGenBase) 153 { 154 this.sandGen = new WorldGenSand(7, Block.sand.blockID); 155 this.gravelAsSandGen = new WorldGenSand(6, Block.gravel.blockID); 156 this.dirtGen = new WorldGenMinable(Block.dirt.blockID, 32); 157 this.gravelGen = new WorldGenMinable(Block.gravel.blockID, 32); 158 this.coalGen = new WorldGenMinable(Block.oreCoal.blockID, 16); 159 this.ironGen = new WorldGenMinable(Block.oreIron.blockID, 8); 160 this.goldGen = new WorldGenMinable(Block.oreGold.blockID, 8); 161 this.redstoneGen = new WorldGenMinable(Block.oreRedstone.blockID, 7); 162 this.diamondGen = new WorldGenMinable(Block.oreDiamond.blockID, 7); 163 this.lapisGen = new WorldGenMinable(Block.oreLapis.blockID, 6); 164 this.plantYellowGen = new WorldGenFlowers(Block.plantYellow.blockID); 165 this.plantRedGen = new WorldGenFlowers(Block.plantRed.blockID); 166 this.mushroomBrownGen = new WorldGenFlowers(Block.mushroomBrown.blockID); 167 this.mushroomRedGen = new WorldGenFlowers(Block.mushroomRed.blockID); 168 this.bigMushroomGen = new WorldGenBigMushroom(); 169 this.reedGen = new WorldGenReed(); 170 this.cactusGen = new WorldGenCactus(); 171 this.waterlilyGen = new WorldGenWaterlily(); 172 this.waterlilyPerChunk = 0; 173 this.treesPerChunk = 0; 174 this.flowersPerChunk = 2; 175 this.grassPerChunk = 1; 176 this.deadBushPerChunk = 0; 177 this.mushroomsPerChunk = 0; 178 this.reedsPerChunk = 0; 179 this.cactiPerChunk = 0; 180 this.sandPerChunk = 1; 181 this.sandPerChunk2 = 3; 182 this.clayPerChunk = 1; 183 this.bigMushroomsPerChunk = 0; 184 this.generateLakes = true; 185 this.biome = par1BiomeGenBase; 186 } 187 188 /** 189 * Decorates the world. Calls code that was formerly (pre-1.8) in ChunkProviderGenerate.populate 190 */ 191 public void decorate(World par1World, Random par2Random, int par3, int par4) 192 { 193 if (this.currentWorld != null) 194 { 195 throw new RuntimeException("Already decorating!!"); 196 } 197 else 198 { 199 this.currentWorld = par1World; 200 this.randomGenerator = par2Random; 201 this.chunk_X = par3; 202 this.chunk_Z = par4; 203 this.decorate(); 204 this.currentWorld = null; 205 this.randomGenerator = null; 206 } 207 } 208 209 /** 210 * The method that does the work of actually decorating chunks 211 */ 212 protected void decorate() 213 { 214 MinecraftForge.EVENT_BUS.post(new DecorateBiomeEvent.Pre(currentWorld, randomGenerator, chunk_X, chunk_Z)); 215 216 this.generateOres(); 217 int var1; 218 int var2; 219 int var3; 220 221 boolean doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, SAND); 222 for (var1 = 0; doGen && var1 < this.sandPerChunk2; ++var1) 223 { 224 var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 225 var3 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 226 this.sandGen.generate(this.currentWorld, this.randomGenerator, var2, this.currentWorld.getTopSolidOrLiquidBlock(var2, var3), var3); 227 } 228 229 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, CLAY); 230 for (var1 = 0; doGen && var1 < this.clayPerChunk; ++var1) 231 { 232 var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 233 var3 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 234 this.clayGen.generate(this.currentWorld, this.randomGenerator, var2, this.currentWorld.getTopSolidOrLiquidBlock(var2, var3), var3); 235 } 236 237 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, SAND_PASS2); 238 for (var1 = 0; doGen && var1 < this.sandPerChunk; ++var1) 239 { 240 var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 241 var3 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 242 this.sandGen.generate(this.currentWorld, this.randomGenerator, var2, this.currentWorld.getTopSolidOrLiquidBlock(var2, var3), var3); 243 } 244 245 var1 = this.treesPerChunk; 246 247 if (this.randomGenerator.nextInt(10) == 0) 248 { 249 ++var1; 250 } 251 252 int var4; 253 254 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, TREE); 255 for (var2 = 0; doGen && var2 < var1; ++var2) 256 { 257 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 258 var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 259 WorldGenerator var5 = this.biome.getRandomWorldGenForTrees(this.randomGenerator); 260 var5.setScale(1.0D, 1.0D, 1.0D); 261 var5.generate(this.currentWorld, this.randomGenerator, var3, this.currentWorld.getHeightValue(var3, var4), var4); 262 } 263 264 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, BIG_SHROOM); 265 for (var2 = 0; doGen && var2 < this.bigMushroomsPerChunk; ++var2) 266 { 267 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 268 var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 269 this.bigMushroomGen.generate(this.currentWorld, this.randomGenerator, var3, this.currentWorld.getHeightValue(var3, var4), var4); 270 } 271 272 int var7; 273 274 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, FLOWERS); 275 for (var2 = 0; doGen && var2 < this.flowersPerChunk; ++var2) 276 { 277 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 278 var4 = this.randomGenerator.nextInt(128); 279 var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 280 this.plantYellowGen.generate(this.currentWorld, this.randomGenerator, var3, var4, var7); 281 282 if (this.randomGenerator.nextInt(4) == 0) 283 { 284 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 285 var4 = this.randomGenerator.nextInt(128); 286 var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 287 this.plantRedGen.generate(this.currentWorld, this.randomGenerator, var3, var4, var7); 288 } 289 } 290 291 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, GRASS); 292 for (var2 = 0; doGen && var2 < this.grassPerChunk; ++var2) 293 { 294 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 295 var4 = this.randomGenerator.nextInt(128); 296 var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 297 WorldGenerator var6 = this.biome.getRandomWorldGenForGrass(this.randomGenerator); 298 var6.generate(this.currentWorld, this.randomGenerator, var3, var4, var7); 299 } 300 301 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, DEAD_BUSH); 302 for (var2 = 0; doGen && var2 < this.deadBushPerChunk; ++var2) 303 { 304 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 305 var4 = this.randomGenerator.nextInt(128); 306 var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 307 (new WorldGenDeadBush(Block.deadBush.blockID)).generate(this.currentWorld, this.randomGenerator, var3, var4, var7); 308 } 309 310 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, LILYPAD); 311 for (var2 = 0; doGen && var2 < this.waterlilyPerChunk; ++var2) 312 { 313 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 314 var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 315 316 for (var7 = this.randomGenerator.nextInt(128); var7 > 0 && this.currentWorld.getBlockId(var3, var7 - 1, var4) == 0; --var7) 317 { 318 ; 319 } 320 321 this.waterlilyGen.generate(this.currentWorld, this.randomGenerator, var3, var7, var4); 322 } 323 324 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, SHROOM); 325 for (var2 = 0; doGen && var2 < this.mushroomsPerChunk; ++var2) 326 { 327 if (this.randomGenerator.nextInt(4) == 0) 328 { 329 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 330 var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 331 var7 = this.currentWorld.getHeightValue(var3, var4); 332 this.mushroomBrownGen.generate(this.currentWorld, this.randomGenerator, var3, var7, var4); 333 } 334 335 if (this.randomGenerator.nextInt(8) == 0) 336 { 337 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 338 var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 339 var7 = this.randomGenerator.nextInt(128); 340 this.mushroomRedGen.generate(this.currentWorld, this.randomGenerator, var3, var7, var4); 341 } 342 } 343 344 if (doGen && this.randomGenerator.nextInt(4) == 0) 345 { 346 var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 347 var3 = this.randomGenerator.nextInt(128); 348 var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 349 this.mushroomBrownGen.generate(this.currentWorld, this.randomGenerator, var2, var3, var4); 350 } 351 352 if (doGen && this.randomGenerator.nextInt(8) == 0) 353 { 354 var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 355 var3 = this.randomGenerator.nextInt(128); 356 var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 357 this.mushroomRedGen.generate(this.currentWorld, this.randomGenerator, var2, var3, var4); 358 } 359 360 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, REED); 361 for (var2 = 0; doGen && var2 < this.reedsPerChunk; ++var2) 362 { 363 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 364 var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 365 var7 = this.randomGenerator.nextInt(128); 366 this.reedGen.generate(this.currentWorld, this.randomGenerator, var3, var7, var4); 367 } 368 369 for (var2 = 0; doGen && var2 < 10; ++var2) 370 { 371 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 372 var4 = this.randomGenerator.nextInt(128); 373 var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 374 this.reedGen.generate(this.currentWorld, this.randomGenerator, var3, var4, var7); 375 } 376 377 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, PUMPKIN); 378 if (doGen && this.randomGenerator.nextInt(32) == 0) 379 { 380 var2 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 381 var3 = this.randomGenerator.nextInt(128); 382 var4 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 383 (new WorldGenPumpkin()).generate(this.currentWorld, this.randomGenerator, var2, var3, var4); 384 } 385 386 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, CACTUS); 387 for (var2 = 0; doGen && var2 < this.cactiPerChunk; ++var2) 388 { 389 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 390 var4 = this.randomGenerator.nextInt(128); 391 var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 392 this.cactusGen.generate(this.currentWorld, this.randomGenerator, var3, var4, var7); 393 } 394 395 doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, LAKE); 396 if (doGen && this.generateLakes) 397 { 398 for (var2 = 0; var2 < 50; ++var2) 399 { 400 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 401 var4 = this.randomGenerator.nextInt(this.randomGenerator.nextInt(120) + 8); 402 var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 403 (new WorldGenLiquids(Block.waterMoving.blockID)).generate(this.currentWorld, this.randomGenerator, var3, var4, var7); 404 } 405 406 for (var2 = 0; var2 < 20; ++var2) 407 { 408 var3 = this.chunk_X + this.randomGenerator.nextInt(16) + 8; 409 var4 = this.randomGenerator.nextInt(this.randomGenerator.nextInt(this.randomGenerator.nextInt(112) + 8) + 8); 410 var7 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8; 411 (new WorldGenLiquids(Block.lavaMoving.blockID)).generate(this.currentWorld, this.randomGenerator, var3, var4, var7); 412 } 413 } 414 415 MinecraftForge.EVENT_BUS.post(new DecorateBiomeEvent.Post(currentWorld, randomGenerator, chunk_X, chunk_Z)); 416 } 417 418 /** 419 * Standard ore generation helper. Generates most ores. 420 */ 421 protected void genStandardOre1(int par1, WorldGenerator par2WorldGenerator, int par3, int par4) 422 { 423 for (int var5 = 0; var5 < par1; ++var5) 424 { 425 int var6 = this.chunk_X + this.randomGenerator.nextInt(16); 426 int var7 = this.randomGenerator.nextInt(par4 - par3) + par3; 427 int var8 = this.chunk_Z + this.randomGenerator.nextInt(16); 428 par2WorldGenerator.generate(this.currentWorld, this.randomGenerator, var6, var7, var8); 429 } 430 } 431 432 /** 433 * Standard ore generation helper. Generates Lapis Lazuli. 434 */ 435 protected void genStandardOre2(int par1, WorldGenerator par2WorldGenerator, int par3, int par4) 436 { 437 for (int var5 = 0; var5 < par1; ++var5) 438 { 439 int var6 = this.chunk_X + this.randomGenerator.nextInt(16); 440 int var7 = this.randomGenerator.nextInt(par4) + this.randomGenerator.nextInt(par4) + (par3 - par4); 441 int var8 = this.chunk_Z + this.randomGenerator.nextInt(16); 442 par2WorldGenerator.generate(this.currentWorld, this.randomGenerator, var6, var7, var8); 443 } 444 } 445 446 /** 447 * Generates ores in the current chunk 448 */ 449 protected void generateOres() 450 { 451 MinecraftForge.ORE_GEN_BUS.post(new OreGenEvent.Pre(currentWorld, randomGenerator, chunk_X, chunk_Z)); 452 if (TerrainGen.generateOre(currentWorld, randomGenerator, dirtGen, chunk_X, chunk_Z, DIRT)) 453 this.genStandardOre1(20, this.dirtGen, 0, 128); 454 if (TerrainGen.generateOre(currentWorld, randomGenerator, gravelGen, chunk_X, chunk_Z, GRAVEL)) 455 this.genStandardOre1(10, this.gravelGen, 0, 128); 456 if (TerrainGen.generateOre(currentWorld, randomGenerator, coalGen, chunk_X, chunk_Z, COAL)) 457 this.genStandardOre1(20, this.coalGen, 0, 128); 458 if (TerrainGen.generateOre(currentWorld, randomGenerator, ironGen, chunk_X, chunk_Z, IRON)) 459 this.genStandardOre1(20, this.ironGen, 0, 64); 460 if (TerrainGen.generateOre(currentWorld, randomGenerator, goldGen, chunk_X, chunk_Z, GOLD)) 461 this.genStandardOre1(2, this.goldGen, 0, 32); 462 if (TerrainGen.generateOre(currentWorld, randomGenerator, redstoneGen, chunk_X, chunk_Z, REDSTONE)) 463 this.genStandardOre1(8, this.redstoneGen, 0, 16); 464 if (TerrainGen.generateOre(currentWorld, randomGenerator, diamondGen, chunk_X, chunk_Z, DIAMOND)) 465 this.genStandardOre1(1, this.diamondGen, 0, 16); 466 if (TerrainGen.generateOre(currentWorld, randomGenerator, lapisGen, chunk_X, chunk_Z, LAPIS)) 467 this.genStandardOre2(1, this.lapisGen, 16, 16); 468 MinecraftForge.ORE_GEN_BUS.post(new OreGenEvent.Post(currentWorld, randomGenerator, chunk_X, chunk_Z)); 469 } 470 }