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        protected World currentWorld;
028    
029        /** The Biome Decorator's random number generator. */
030        protected Random randomGenerator;
031    
032        /** The X-coordinate of the chunk currently being decorated */
033        protected int chunk_X;
034    
035        /** The Z-coordinate of the chunk currently being decorated */
036        protected int chunk_Z;
037    
038        /** The biome generator object. */
039        protected BiomeGenBase biome;
040    
041        /** The clay generator. */
042        protected WorldGenerator clayGen = new WorldGenClay(4);
043    
044        /** The sand generator. */
045        protected WorldGenerator sandGen;
046    
047        /** The gravel generator. */
048        protected WorldGenerator gravelAsSandGen;
049    
050        /** The dirt generator. */
051        protected WorldGenerator dirtGen;
052        protected WorldGenerator gravelGen;
053        protected WorldGenerator coalGen;
054        protected WorldGenerator ironGen;
055    
056        /** Field that holds gold WorldGenMinable */
057        protected WorldGenerator goldGen;
058    
059        /** Field that holds redstone WorldGenMinable */
060        protected WorldGenerator redstoneGen;
061    
062        /** Field that holds diamond WorldGenMinable */
063        protected WorldGenerator diamondGen;
064    
065        /** Field that holds Lapis WorldGenMinable */
066        protected WorldGenerator lapisGen;
067    
068        /** Field that holds one of the plantYellow WorldGenFlowers */
069        protected WorldGenerator plantYellowGen;
070    
071        /** Field that holds one of the plantRed WorldGenFlowers */
072        protected WorldGenerator plantRedGen;
073    
074        /** Field that holds mushroomBrown WorldGenFlowers */
075        protected WorldGenerator mushroomBrownGen;
076    
077        /** Field that holds mushroomRed WorldGenFlowers */
078        protected WorldGenerator mushroomRedGen;
079    
080        /** Field that holds big mushroom generator */
081        protected WorldGenerator bigMushroomGen;
082    
083        /** Field that holds WorldGenReed */
084        protected WorldGenerator reedGen;
085    
086        /** Field that holds WorldGenCactus */
087        protected WorldGenerator cactusGen;
088    
089        /** The water lily generation! */
090        protected WorldGenerator waterlilyGen;
091    
092        /** Amount of waterlilys per chunk. */
093        protected 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        protected 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        protected int flowersPerChunk;
105    
106        /** The amount of tall grass to generate per chunk. */
107        protected int grassPerChunk;
108    
109        /**
110         * The number of dead bushes to generate per chunk. Used in deserts and swamps.
111         */
112        protected 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        protected 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        protected int reedsPerChunk;
124    
125        /**
126         * The number of cactus plants to generate per chunk. Cacti only work on sand.
127         */
128        protected 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        protected 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        protected int sandPerChunk2;
140    
141        /**
142         * The number of clay patches to generate per chunk. Only generates when part of it is underwater.
143         */
144        protected int clayPerChunk;
145    
146        /** Amount of big mushrooms per chunk */
147        protected 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    }