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 }