001    package net.minecraft.block;
002    
003    import java.util.Random;
004    import net.minecraft.block.material.Material;
005    import net.minecraft.creativetab.CreativeTabs;
006    import net.minecraft.entity.item.EntityFallingSand;
007    import net.minecraft.world.World;
008    
009    public 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, int par2)
015        {
016            super(par1, par2, Material.sand);
017            this.setCreativeTab(CreativeTabs.tabBlock);
018        }
019    
020        public BlockSand(int par1, int par2, Material par3Material)
021        {
022            super(par1, par2, par3Material);
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());
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());
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 var8 = 32;
061    
062                if (!fallInstantly && par1World.checkChunksExist(par2 - var8, par3 - var8, par4 - var8, par2 + var8, par3 + var8, par4 + var8))
063                {
064                    if (!par1World.isRemote)
065                    {
066                        EntityFallingSand var9 = 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(var9);
068                        par1World.spawnEntityInWorld(var9);
069                    }
070                }
071                else
072                {
073                    par1World.setBlockWithNotify(par2, par3, par4, 0);
074    
075                    while (canFallBelow(par1World, par2, par3 - 1, par4) && par3 > 0)
076                    {
077                        --par3;
078                    }
079    
080                    if (par3 > 0)
081                    {
082                        par1World.setBlockWithNotify(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()
097        {
098            return 5;
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 var4 = par0World.getBlockId(par1, par2, par3);
107    
108            if (var4 == 0)
109            {
110                return true;
111            }
112            else if (var4 == Block.fire.blockID)
113            {
114                return true;
115            }
116            else
117            {
118                Material var5 = Block.blocksList[var4].blockMaterial;
119                return var5 == Material.water ? true : var5 == 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    }