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