001package net.minecraft.world.gen.feature;
002
003import java.util.Random;
004import net.minecraft.block.Block;
005import net.minecraft.block.BlockSapling;
006import net.minecraft.util.MathHelper;
007import net.minecraft.world.World;
008import net.minecraftforge.common.ForgeDirection;
009
010public class WorldGenHugeTrees extends WorldGenerator
011{
012    /** The base height of the tree */
013    private final int baseHeight;
014
015    /** Sets the metadata for the wood blocks used */
016    private final int woodMetadata;
017
018    /** Sets the metadata for the leaves used in huge trees */
019    private final int leavesMetadata;
020
021    public WorldGenHugeTrees(boolean par1, int par2, int par3, int par4)
022    {
023        super(par1);
024        this.baseHeight = par2;
025        this.woodMetadata = par3;
026        this.leavesMetadata = par4;
027    }
028
029    public boolean generate(World par1World, Random par2Random, int par3, int par4, int par5)
030    {
031        int l = par2Random.nextInt(3) + this.baseHeight;
032        boolean flag = true;
033
034        if (par4 >= 1 && par4 + l + 1 <= 256)
035        {
036            int i1;
037            int j1;
038            int k1;
039            int l1;
040
041            for (i1 = par4; i1 <= par4 + 1 + l; ++i1)
042            {
043                byte b0 = 2;
044
045                if (i1 == par4)
046                {
047                    b0 = 1;
048                }
049
050                if (i1 >= par4 + 1 + l - 2)
051                {
052                    b0 = 2;
053                }
054
055                for (j1 = par3 - b0; j1 <= par3 + b0 && flag; ++j1)
056                {
057                    for (k1 = par5 - b0; k1 <= par5 + b0 && flag; ++k1)
058                    {
059                        if (i1 >= 0 && i1 < 256)
060                        {
061                            l1 = par1World.getBlockId(j1, i1, k1);
062
063                            if (l1 != 0 &&
064                               (Block.blocksList[l1] != null && !Block.blocksList[l1].isLeaves(par1World, j1, i1, k1)) &&
065                               l1 != Block.grass.blockID &&
066                               l1 != Block.dirt.blockID &&
067                               (Block.blocksList[l1] != null && !Block.blocksList[l1].isWood(par1World, j1, i1, k1)) &&
068                               l1 != Block.sapling.blockID)
069                            {
070                                flag = false;
071                            }
072                        }
073                        else
074                        {
075                            flag = false;
076                        }
077                    }
078                }
079            }
080
081            if (!flag)
082            {
083                return false;
084            }
085            else
086            {
087                i1 = par1World.getBlockId(par3, par4 - 1, par5);
088
089                Block soil = Block.blocksList[i1];
090                boolean isValidSoil = soil != null && soil.canSustainPlant(par1World, par3, par4 - 1, par5, ForgeDirection.UP, (BlockSapling)Block.sapling);
091
092                if (isValidSoil && par4 < 256 - l - 1)
093                {
094                    onPlantGrow(par1World, par3,     par4 - 1, par5,     par3, par4, par5);
095                    onPlantGrow(par1World, par3 + 1, par4 - 1, par5,     par3, par4, par5);
096                    onPlantGrow(par1World, par3,     par4 - 1, par5 + 1, par3, par4, par5);
097                    onPlantGrow(par1World, par3 + 1, par4 - 1, par5 + 1, par3, par4, par5);
098                    this.growLeaves(par1World, par3, par5, par4 + l, 2, par2Random);
099
100                    for (int i2 = par4 + l - 2 - par2Random.nextInt(4); i2 > par4 + l / 2; i2 -= 2 + par2Random.nextInt(4))
101                    {
102                        float f = par2Random.nextFloat() * (float)Math.PI * 2.0F;
103                        k1 = par3 + (int)(0.5F + MathHelper.cos(f) * 4.0F);
104                        l1 = par5 + (int)(0.5F + MathHelper.sin(f) * 4.0F);
105                        this.growLeaves(par1World, k1, l1, i2, 0, par2Random);
106
107                        for (int j2 = 0; j2 < 5; ++j2)
108                        {
109                            k1 = par3 + (int)(1.5F + MathHelper.cos(f) * (float)j2);
110                            l1 = par5 + (int)(1.5F + MathHelper.sin(f) * (float)j2);
111                            this.setBlockAndMetadata(par1World, k1, i2 - 3 + j2 / 2, l1, Block.wood.blockID, this.woodMetadata);
112                        }
113                    }
114
115                    for (j1 = 0; j1 < l; ++j1)
116                    {
117                        k1 = par1World.getBlockId(par3, par4 + j1, par5);
118
119                        if (k1 == 0 || Block.blocksList[k1] == null || Block.blocksList[k1].isLeaves(par1World, par3, par4 + j1, par5))
120                        {
121                            this.setBlockAndMetadata(par1World, par3, par4 + j1, par5, Block.wood.blockID, this.woodMetadata);
122
123                            if (j1 > 0)
124                            {
125                                if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3 - 1, par4 + j1, par5))
126                                {
127                                    this.setBlockAndMetadata(par1World, par3 - 1, par4 + j1, par5, Block.vine.blockID, 8);
128                                }
129
130                                if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3, par4 + j1, par5 - 1))
131                                {
132                                    this.setBlockAndMetadata(par1World, par3, par4 + j1, par5 - 1, Block.vine.blockID, 1);
133                                }
134                            }
135                        }
136
137                        if (j1 < l - 1)
138                        {
139                            k1 = par1World.getBlockId(par3 + 1, par4 + j1, par5);
140
141                            if (k1 == 0 || Block.blocksList[k1] == null || Block.blocksList[k1].isLeaves(par1World, par3 + 1, par4 + j1, par5))
142                            {
143                                this.setBlockAndMetadata(par1World, par3 + 1, par4 + j1, par5, Block.wood.blockID, this.woodMetadata);
144
145                                if (j1 > 0)
146                                {
147                                    if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3 + 2, par4 + j1, par5))
148                                    {
149                                        this.setBlockAndMetadata(par1World, par3 + 2, par4 + j1, par5, Block.vine.blockID, 2);
150                                    }
151
152                                    if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3 + 1, par4 + j1, par5 - 1))
153                                    {
154                                        this.setBlockAndMetadata(par1World, par3 + 1, par4 + j1, par5 - 1, Block.vine.blockID, 1);
155                                    }
156                                }
157                            }
158
159                            k1 = par1World.getBlockId(par3 + 1, par4 + j1, par5 + 1);
160
161                            if (k1 == 0 || Block.blocksList[k1] == null || Block.blocksList[k1].isLeaves(par1World, par3 + 1, par4 + j1, par5 + 1))
162                            {
163                                this.setBlockAndMetadata(par1World, par3 + 1, par4 + j1, par5 + 1, Block.wood.blockID, this.woodMetadata);
164
165                                if (j1 > 0)
166                                {
167                                    if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3 + 2, par4 + j1, par5 + 1))
168                                    {
169                                        this.setBlockAndMetadata(par1World, par3 + 2, par4 + j1, par5 + 1, Block.vine.blockID, 2);
170                                    }
171
172                                    if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3 + 1, par4 + j1, par5 + 2))
173                                    {
174                                        this.setBlockAndMetadata(par1World, par3 + 1, par4 + j1, par5 + 2, Block.vine.blockID, 4);
175                                    }
176                                }
177                            }
178
179                            k1 = par1World.getBlockId(par3, par4 + j1, par5 + 1);
180
181                            if (k1 == 0 || Block.blocksList[k1] == null || Block.blocksList[k1].isLeaves(par1World, par3, par4 + j1, par5 + 1))
182                            {
183                                this.setBlockAndMetadata(par1World, par3, par4 + j1, par5 + 1, Block.wood.blockID, this.woodMetadata);
184
185                                if (j1 > 0)
186                                {
187                                    if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3 - 1, par4 + j1, par5 + 1))
188                                    {
189                                        this.setBlockAndMetadata(par1World, par3 - 1, par4 + j1, par5 + 1, Block.vine.blockID, 8);
190                                    }
191
192                                    if (par2Random.nextInt(3) > 0 && par1World.isAirBlock(par3, par4 + j1, par5 + 2))
193                                    {
194                                        this.setBlockAndMetadata(par1World, par3, par4 + j1, par5 + 2, Block.vine.blockID, 4);
195                                    }
196                                }
197                            }
198                        }
199                    }
200
201                    return true;
202                }
203                else
204                {
205                    return false;
206                }
207            }
208        }
209        else
210        {
211            return false;
212        }
213    }
214
215    private void growLeaves(World par1World, int par2, int par3, int par4, int par5, Random par6Random)
216    {
217        byte b0 = 2;
218
219        for (int i1 = par4 - b0; i1 <= par4; ++i1)
220        {
221            int j1 = i1 - par4;
222            int k1 = par5 + 1 - j1;
223
224            for (int l1 = par2 - k1; l1 <= par2 + k1 + 1; ++l1)
225            {
226                int i2 = l1 - par2;
227
228                for (int j2 = par3 - k1; j2 <= par3 + k1 + 1; ++j2)
229                {
230                    int k2 = j2 - par3;
231
232                    if ((i2 >= 0 || k2 >= 0 || i2 * i2 + k2 * k2 <= k1 * k1) && (i2 <= 0 && k2 <= 0 || i2 * i2 + k2 * k2 <= (k1 + 1) * (k1 + 1)) && (par6Random.nextInt(4) != 0 || i2 * i2 + k2 * k2 <= (k1 - 1) * (k1 - 1)))
233                    {
234                        int l2 = par1World.getBlockId(l1, i1, j2);
235                        Block block = Block.blocksList[l2];
236
237                        if (block == null || block.canBeReplacedByLeaves(par1World, l1, i1, j2))
238                        {
239                            this.setBlockAndMetadata(par1World, l1, i1, j2, Block.leaves.blockID, this.leavesMetadata);
240                        }
241                    }
242                }
243            }
244        }
245    }
246
247    private void onPlantGrow(World world, int x, int y, int z, int sourceX, int sourceY, int sourceZ)
248    {
249        Block block = Block.blocksList[world.getBlockId(x, y, z)];
250        if (block != null)
251        {
252            block.onPlantGrow(world, x, y, z, sourceX, sourceY, sourceZ);
253        }
254    }
255}