001package net.minecraft.world.biome;
002
003import java.util.Random;
004import net.minecraft.block.Block;
005import net.minecraft.world.World;
006import net.minecraft.world.gen.feature.WorldGenBigMushroom;
007import net.minecraft.world.gen.feature.WorldGenCactus;
008import net.minecraft.world.gen.feature.WorldGenClay;
009import net.minecraft.world.gen.feature.WorldGenDeadBush;
010import net.minecraft.world.gen.feature.WorldGenFlowers;
011import net.minecraft.world.gen.feature.WorldGenLiquids;
012import net.minecraft.world.gen.feature.WorldGenMinable;
013import net.minecraft.world.gen.feature.WorldGenPumpkin;
014import net.minecraft.world.gen.feature.WorldGenReed;
015import net.minecraft.world.gen.feature.WorldGenSand;
016import net.minecraft.world.gen.feature.WorldGenWaterlily;
017import net.minecraft.world.gen.feature.WorldGenerator;
018
019import static net.minecraftforge.event.terraingen.DecorateBiomeEvent.Decorate.EventType.*;
020import static net.minecraftforge.event.terraingen.OreGenEvent.GenerateMinable.EventType.*;
021import net.minecraftforge.common.*;
022import net.minecraftforge.event.terraingen.*;
023
024public 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 i;
218        int j;
219        int k;
220
221        boolean doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, SAND);
222        for (i = 0; doGen && i < this.sandPerChunk2; ++i)
223        {
224            j = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
225            k = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
226            this.sandGen.generate(this.currentWorld, this.randomGenerator, j, this.currentWorld.getTopSolidOrLiquidBlock(j, k), k);
227        }
228
229        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, CLAY);
230        for (i = 0; doGen && i < this.clayPerChunk; ++i)
231        {
232            j = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
233            k = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
234            this.clayGen.generate(this.currentWorld, this.randomGenerator, j, this.currentWorld.getTopSolidOrLiquidBlock(j, k), k);
235        }
236
237        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, SAND_PASS2);
238        for (i = 0; doGen && i < this.sandPerChunk; ++i)
239        {
240            j = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
241            k = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
242            this.sandGen.generate(this.currentWorld, this.randomGenerator, j, this.currentWorld.getTopSolidOrLiquidBlock(j, k), k);
243        }
244
245        i = this.treesPerChunk;
246
247        if (this.randomGenerator.nextInt(10) == 0)
248        {
249            ++i;
250        }
251
252        int l;
253
254        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, TREE);
255        for (j = 0; doGen && j < i; ++j)
256        {
257            k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
258            l = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
259            WorldGenerator worldgenerator = this.biome.getRandomWorldGenForTrees(this.randomGenerator);
260            worldgenerator.setScale(1.0D, 1.0D, 1.0D);
261            worldgenerator.generate(this.currentWorld, this.randomGenerator, k, this.currentWorld.getHeightValue(k, l), l);
262        }
263
264        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, BIG_SHROOM);
265        for (j = 0; doGen && j < this.bigMushroomsPerChunk; ++j)
266        {
267            k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
268            l = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
269            this.bigMushroomGen.generate(this.currentWorld, this.randomGenerator, k, this.currentWorld.getHeightValue(k, l), l);
270        }
271
272        int i1;
273
274        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, FLOWERS);
275        for (j = 0; doGen && j < this.flowersPerChunk; ++j)
276        {
277            k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
278            l = this.randomGenerator.nextInt(128);
279            i1 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
280            this.plantYellowGen.generate(this.currentWorld, this.randomGenerator, k, l, i1);
281
282            if (this.randomGenerator.nextInt(4) == 0)
283            {
284                k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
285                l = this.randomGenerator.nextInt(128);
286                i1 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
287                this.plantRedGen.generate(this.currentWorld, this.randomGenerator, k, l, i1);
288            }
289        }
290
291        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, GRASS);
292        for (j = 0; doGen && j < this.grassPerChunk; ++j)
293        {
294            k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
295            l = this.randomGenerator.nextInt(128);
296            i1 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
297            WorldGenerator worldgenerator1 = this.biome.getRandomWorldGenForGrass(this.randomGenerator);
298            worldgenerator1.generate(this.currentWorld, this.randomGenerator, k, l, i1);
299        }
300
301        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, DEAD_BUSH);
302        for (j = 0; doGen && j < this.deadBushPerChunk; ++j)
303        {
304            k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
305            l = this.randomGenerator.nextInt(128);
306            i1 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
307            (new WorldGenDeadBush(Block.deadBush.blockID)).generate(this.currentWorld, this.randomGenerator, k, l, i1);
308        }
309
310        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, LILYPAD);
311        for (j = 0; doGen && j < this.waterlilyPerChunk; ++j)
312        {
313            k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
314            l = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
315
316            for (i1 = this.randomGenerator.nextInt(128); i1 > 0 && this.currentWorld.getBlockId(k, i1 - 1, l) == 0; --i1)
317            {
318                ;
319            }
320
321            this.waterlilyGen.generate(this.currentWorld, this.randomGenerator, k, i1, l);
322        }
323
324        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, SHROOM);
325        for (j = 0; doGen && j < this.mushroomsPerChunk; ++j)
326        {
327            if (this.randomGenerator.nextInt(4) == 0)
328            {
329                k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
330                l = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
331                i1 = this.currentWorld.getHeightValue(k, l);
332                this.mushroomBrownGen.generate(this.currentWorld, this.randomGenerator, k, i1, l);
333            }
334
335            if (this.randomGenerator.nextInt(8) == 0)
336            {
337                k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
338                l = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
339                i1 = this.randomGenerator.nextInt(128);
340                this.mushroomRedGen.generate(this.currentWorld, this.randomGenerator, k, i1, l);
341            }
342        }
343
344        if (doGen && this.randomGenerator.nextInt(4) == 0)
345        {
346            j = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
347            k = this.randomGenerator.nextInt(128);
348            l = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
349            this.mushroomBrownGen.generate(this.currentWorld, this.randomGenerator, j, k, l);
350        }
351
352        if (doGen && this.randomGenerator.nextInt(8) == 0)
353        {
354            j = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
355            k = this.randomGenerator.nextInt(128);
356            l = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
357            this.mushroomRedGen.generate(this.currentWorld, this.randomGenerator, j, k, l);
358        }
359
360        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, REED);
361        for (j = 0; doGen && j < this.reedsPerChunk; ++j)
362        {
363            k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
364            l = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
365            i1 = this.randomGenerator.nextInt(128);
366            this.reedGen.generate(this.currentWorld, this.randomGenerator, k, i1, l);
367        }
368
369        for (j = 0; doGen && j < 10; ++j)
370        {
371            k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
372            l = this.randomGenerator.nextInt(128);
373            i1 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
374            this.reedGen.generate(this.currentWorld, this.randomGenerator, k, l, i1);
375        }
376
377        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, PUMPKIN);
378        if (doGen && this.randomGenerator.nextInt(32) == 0)
379        {
380            j = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
381            k = this.randomGenerator.nextInt(128);
382            l = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
383            (new WorldGenPumpkin()).generate(this.currentWorld, this.randomGenerator, j, k, l);
384        }
385
386        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, CACTUS);
387        for (j = 0; doGen && j < this.cactiPerChunk; ++j)
388        {
389            k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
390            l = this.randomGenerator.nextInt(128);
391            i1 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
392            this.cactusGen.generate(this.currentWorld, this.randomGenerator, k, l, i1);
393        }
394
395        doGen = TerrainGen.decorate(currentWorld, randomGenerator, chunk_X, chunk_Z, LAKE);
396        if (doGen && this.generateLakes)
397        {
398            for (j = 0; j < 50; ++j)
399            {
400                k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
401                l = this.randomGenerator.nextInt(this.randomGenerator.nextInt(120) + 8);
402                i1 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
403                (new WorldGenLiquids(Block.waterMoving.blockID)).generate(this.currentWorld, this.randomGenerator, k, l, i1);
404            }
405
406            for (j = 0; j < 20; ++j)
407            {
408                k = this.chunk_X + this.randomGenerator.nextInt(16) + 8;
409                l = this.randomGenerator.nextInt(this.randomGenerator.nextInt(this.randomGenerator.nextInt(112) + 8) + 8);
410                i1 = this.chunk_Z + this.randomGenerator.nextInt(16) + 8;
411                (new WorldGenLiquids(Block.lavaMoving.blockID)).generate(this.currentWorld, this.randomGenerator, k, l, i1);
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 l = 0; l < par1; ++l)
424        {
425            int i1 = this.chunk_X + this.randomGenerator.nextInt(16);
426            int j1 = this.randomGenerator.nextInt(par4 - par3) + par3;
427            int k1 = this.chunk_Z + this.randomGenerator.nextInt(16);
428            par2WorldGenerator.generate(this.currentWorld, this.randomGenerator, i1, j1, k1);
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 l = 0; l < par1; ++l)
438        {
439            int i1 = this.chunk_X + this.randomGenerator.nextInt(16);
440            int j1 = this.randomGenerator.nextInt(par4) + this.randomGenerator.nextInt(par4) + (par3 - par4);
441            int k1 = this.chunk_Z + this.randomGenerator.nextInt(16);
442            par2WorldGenerator.generate(this.currentWorld, this.randomGenerator, i1, j1, k1);
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}