001package net.minecraft.block;
002
003import java.util.Random;
004import net.minecraft.block.material.Material;
005import net.minecraft.creativetab.CreativeTabs;
006import net.minecraft.entity.item.EntityFallingSand;
007import net.minecraft.world.World;
008
009public class BlockSand extends Block
010{
011    /** Do blocks fall instantly to where they stop or do they fall over time */
012    public static boolean fallInstantly = false;
013
014    public BlockSand(int par1)
015    {
016        super(par1, Material.sand);
017        this.setCreativeTab(CreativeTabs.tabBlock);
018    }
019
020    public BlockSand(int par1, Material par2Material)
021    {
022        super(par1, par2Material);
023    }
024
025    /**
026     * Called whenever the block is added into the world. Args: world, x, y, z
027     */
028    public void onBlockAdded(World par1World, int par2, int par3, int par4)
029    {
030        par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
031    }
032
033    /**
034     * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
035     * their own) Args: x, y, z, neighbor blockID
036     */
037    public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
038    {
039        par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World));
040    }
041
042    /**
043     * Ticks the block if it's been scheduled
044     */
045    public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
046    {
047        if (!par1World.isRemote)
048        {
049            this.tryToFall(par1World, par2, par3, par4);
050        }
051    }
052
053    /**
054     * If there is space to fall below will start this block falling
055     */
056    private void tryToFall(World par1World, int par2, int par3, int par4)
057    {
058        if (canFallBelow(par1World, par2, par3 - 1, par4) && par3 >= 0)
059        {
060            byte b0 = 32;
061
062            if (!fallInstantly && par1World.checkChunksExist(par2 - b0, par3 - b0, par4 - b0, par2 + b0, par3 + b0, par4 + b0))
063            {
064                if (!par1World.isRemote)
065                {
066                    EntityFallingSand entityfallingsand = new EntityFallingSand(par1World, (double)((float)par2 + 0.5F), (double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), this.blockID, par1World.getBlockMetadata(par2, par3, par4));
067                    this.onStartFalling(entityfallingsand);
068                    par1World.spawnEntityInWorld(entityfallingsand);
069                }
070            }
071            else
072            {
073                par1World.setBlockToAir(par2, par3, par4);
074
075                while (canFallBelow(par1World, par2, par3 - 1, par4) && par3 > 0)
076                {
077                    --par3;
078                }
079
080                if (par3 > 0)
081                {
082                    par1World.setBlock(par2, par3, par4, this.blockID);
083                }
084            }
085        }
086    }
087
088    /**
089     * Called when the falling block entity for this block is created
090     */
091    protected void onStartFalling(EntityFallingSand par1EntityFallingSand) {}
092
093    /**
094     * How many world ticks before ticking
095     */
096    public int tickRate(World par1World)
097    {
098        return 2;
099    }
100
101    /**
102     * Checks to see if the sand can fall into the block below it
103     */
104    public static boolean canFallBelow(World par0World, int par1, int par2, int par3)
105    {
106        int l = par0World.getBlockId(par1, par2, par3);
107
108        if (l == 0)
109        {
110            return true;
111        }
112        else if (l == Block.fire.blockID)
113        {
114            return true;
115        }
116        else
117        {
118            Material material = Block.blocksList[l].blockMaterial;
119            return material == Material.water ? true : material == Material.lava;
120        }
121    }
122
123    /**
124     * Called when the falling block entity for this block hits the ground and turns back into a block
125     */
126    public void onFinishFalling(World par1World, int par2, int par3, int par4, int par5) {}
127}