001package net.minecraft.block;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.util.List;
006import java.util.Random;
007import net.minecraft.block.material.Material;
008import net.minecraft.client.renderer.texture.IconRegister;
009import net.minecraft.creativetab.CreativeTabs;
010import net.minecraft.entity.Entity;
011import net.minecraft.entity.EntityLiving;
012import net.minecraft.entity.item.EntityItem;
013import net.minecraft.entity.player.EntityPlayer;
014import net.minecraft.inventory.Container;
015import net.minecraft.item.ItemStack;
016import net.minecraft.nbt.NBTTagCompound;
017import net.minecraft.tileentity.TileEntity;
018import net.minecraft.tileentity.TileEntityHopper;
019import net.minecraft.util.AxisAlignedBB;
020import net.minecraft.util.Facing;
021import net.minecraft.util.Icon;
022import net.minecraft.world.IBlockAccess;
023import net.minecraft.world.World;
024
025public class BlockHopper extends BlockContainer
026{
027    private final Random field_94457_a = new Random();
028    @SideOnly(Side.CLIENT)
029    private Icon field_94455_b;
030    @SideOnly(Side.CLIENT)
031    private Icon field_94456_c;
032    @SideOnly(Side.CLIENT)
033    private Icon field_94454_cO;
034
035    public BlockHopper(int par1)
036    {
037        super(par1, Material.iron);
038        this.setCreativeTab(CreativeTabs.tabRedstone);
039        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
040    }
041
042    /**
043     * Updates the blocks bounds based on its current state. Args: world, x, y, z
044     */
045    public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
046    {
047        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
048    }
049
050    /**
051     * Adds all intersecting collision boxes to a list. (Be sure to only add boxes to the list if they intersect the
052     * mask.) Parameters: World, X, Y, Z, mask, list, colliding entity
053     */
054    public void addCollisionBoxesToList(World par1World, int par2, int par3, int par4, AxisAlignedBB par5AxisAlignedBB, List par6List, Entity par7Entity)
055    {
056        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.625F, 1.0F);
057        super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
058        float f = 0.125F;
059        this.setBlockBounds(0.0F, 0.0F, 0.0F, f, 1.0F, 1.0F);
060        super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
061        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, f);
062        super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
063        this.setBlockBounds(1.0F - f, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
064        super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
065        this.setBlockBounds(0.0F, 0.0F, 1.0F - f, 1.0F, 1.0F, 1.0F);
066        super.addCollisionBoxesToList(par1World, par2, par3, par4, par5AxisAlignedBB, par6List, par7Entity);
067        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
068    }
069
070    /**
071     * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata
072     */
073    public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9)
074    {
075        int j1 = Facing.faceToSide[par5];
076
077        if (j1 == 1)
078        {
079            j1 = 0;
080        }
081
082        return j1;
083    }
084
085    /**
086     * Returns a new instance of a block's tile entity class. Called on placing the block.
087     */
088    public TileEntity createNewTileEntity(World par1World)
089    {
090        return new TileEntityHopper();
091    }
092
093    /**
094     * Called when the block is placed in the world.
095     */
096    public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving, ItemStack par6ItemStack)
097    {
098        super.onBlockPlacedBy(par1World, par2, par3, par4, par5EntityLiving, par6ItemStack);
099
100        if (par6ItemStack.hasDisplayName())
101        {
102            TileEntityHopper tileentityhopper = func_98213_d(par1World, par2, par3, par4);
103            tileentityhopper.func_96115_a(par6ItemStack.getDisplayName());
104        }
105    }
106
107    /**
108     * Called whenever the block is added into the world. Args: world, x, y, z
109     */
110    public void onBlockAdded(World par1World, int par2, int par3, int par4)
111    {
112        super.onBlockAdded(par1World, par2, par3, par4);
113        this.func_96471_k(par1World, par2, par3, par4);
114    }
115
116    /**
117     * Called upon block activation (right click on the block.)
118     */
119    public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
120    {
121        if (par1World.isRemote)
122        {
123            return true;
124        }
125        else
126        {
127            TileEntityHopper tileentityhopper = func_98213_d(par1World, par2, par3, par4);
128
129            if (tileentityhopper != null)
130            {
131                par5EntityPlayer.func_94064_a(tileentityhopper);
132            }
133
134            return true;
135        }
136    }
137
138    /**
139     * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
140     * their own) Args: x, y, z, neighbor blockID
141     */
142    public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
143    {
144        this.func_96471_k(par1World, par2, par3, par4);
145    }
146
147    private void func_96471_k(World par1World, int par2, int par3, int par4)
148    {
149        int l = par1World.getBlockMetadata(par2, par3, par4);
150        int i1 = func_94451_c(l);
151        boolean flag = !par1World.isBlockIndirectlyGettingPowered(par2, par3, par4);
152        boolean flag1 = func_94452_d(l);
153
154        if (flag != flag1)
155        {
156            par1World.setBlockMetadataWithNotify(par2, par3, par4, i1 | (flag ? 0 : 8), 4);
157        }
158    }
159
160    /**
161     * ejects contained items into the world, and notifies neighbours of an update, as appropriate
162     */
163    public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
164    {
165        TileEntityHopper tileentityhopper = (TileEntityHopper)par1World.getBlockTileEntity(par2, par3, par4);
166
167        if (tileentityhopper != null)
168        {
169            for (int j1 = 0; j1 < tileentityhopper.getSizeInventory(); ++j1)
170            {
171                ItemStack itemstack = tileentityhopper.getStackInSlot(j1);
172
173                if (itemstack != null)
174                {
175                    float f = this.field_94457_a.nextFloat() * 0.8F + 0.1F;
176                    float f1 = this.field_94457_a.nextFloat() * 0.8F + 0.1F;
177                    float f2 = this.field_94457_a.nextFloat() * 0.8F + 0.1F;
178
179                    while (itemstack.stackSize > 0)
180                    {
181                        int k1 = this.field_94457_a.nextInt(21) + 10;
182
183                        if (k1 > itemstack.stackSize)
184                        {
185                            k1 = itemstack.stackSize;
186                        }
187
188                        itemstack.stackSize -= k1;
189                        EntityItem entityitem = new EntityItem(par1World, (double)((float)par2 + f), (double)((float)par3 + f1), (double)((float)par4 + f2), new ItemStack(itemstack.itemID, k1, itemstack.getItemDamage()));
190
191                        if (itemstack.hasTagCompound())
192                        {
193                            entityitem.getEntityItem().setTagCompound((NBTTagCompound)itemstack.getTagCompound().copy());
194                        }
195
196                        float f3 = 0.05F;
197                        entityitem.motionX = (double)((float)this.field_94457_a.nextGaussian() * f3);
198                        entityitem.motionY = (double)((float)this.field_94457_a.nextGaussian() * f3 + 0.2F);
199                        entityitem.motionZ = (double)((float)this.field_94457_a.nextGaussian() * f3);
200                        par1World.spawnEntityInWorld(entityitem);
201                    }
202                }
203            }
204        }
205
206        super.breakBlock(par1World, par2, par3, par4, par5, par6);
207    }
208
209    /**
210     * The type of render function that is called for this block
211     */
212    public int getRenderType()
213    {
214        return 38;
215    }
216
217    /**
218     * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
219     */
220    public boolean renderAsNormalBlock()
221    {
222        return false;
223    }
224
225    /**
226     * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
227     * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
228     */
229    public boolean isOpaqueCube()
230    {
231        return false;
232    }
233
234    public static int func_94451_c(int par0)
235    {
236        return par0 & 7;
237    }
238
239    @SideOnly(Side.CLIENT)
240
241    /**
242     * Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
243     * coordinates.  Args: blockAccess, x, y, z, side
244     */
245    public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
246    {
247        return true;
248    }
249
250    @SideOnly(Side.CLIENT)
251
252    /**
253     * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
254     */
255    public Icon getBlockTextureFromSideAndMetadata(int par1, int par2)
256    {
257        return par1 == 1 ? this.field_94456_c : this.field_94455_b;
258    }
259
260    public static boolean func_94452_d(int par0)
261    {
262        return (par0 & 8) != 8;
263    }
264
265    public boolean func_96468_q_()
266    {
267        return true;
268    }
269
270    public int func_94328_b_(World par1World, int par2, int par3, int par4, int par5)
271    {
272        return Container.func_94526_b(func_98213_d(par1World, par2, par3, par4));
273    }
274
275    @SideOnly(Side.CLIENT)
276    public void func_94332_a(IconRegister par1IconRegister)
277    {
278        this.field_94455_b = par1IconRegister.func_94245_a("hopper");
279        this.field_94456_c = par1IconRegister.func_94245_a("hopper_top");
280        this.field_94454_cO = par1IconRegister.func_94245_a("hopper_inside");
281    }
282
283    @SideOnly(Side.CLIENT)
284    public static Icon func_94453_b(String par0Str)
285    {
286        return par0Str == "hopper" ? Block.field_94340_cs.field_94455_b : (par0Str == "hopper_inside" ? Block.field_94340_cs.field_94454_cO : null);
287    }
288
289    @SideOnly(Side.CLIENT)
290    public String func_94327_t_()
291    {
292        return "hopper";
293    }
294
295    public static TileEntityHopper func_98213_d(IBlockAccess par0IBlockAccess, int par1, int par2, int par3)
296    {
297        return (TileEntityHopper)par0IBlockAccess.getBlockTileEntity(par1, par2, par3);
298    }
299}