    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}