    001package net.minecraft.entity.item;
    002
    003import net.minecraft.entity.player.EntityPlayer;
    004import net.minecraft.inventory.Container;
    005import net.minecraft.inventory.IInventory;
    006import net.minecraft.item.ItemStack;
    007import net.minecraft.nbt.NBTTagCompound;
    008import net.minecraft.nbt.NBTTagList;
    009import net.minecraft.util.DamageSource;
    010import net.minecraft.world.World;
    011import net.minecraftforge.common.MinecraftForge;
    012import net.minecraftforge.event.entity.minecart.MinecartInteractEvent;
    013
    014public abstract class EntityMinecartContainer extends EntityMinecart implements IInventory
    015{
    016    private ItemStack[] field_94113_a = new ItemStack[36];
    017    private boolean field_94112_b = true;
    018
    019    public EntityMinecartContainer(World par1World)
    020    {
    021        super(par1World);
    022    }
    023
    024    public EntityMinecartContainer(World par1World, double par2, double par4, double par6)
    025    {
    026        super(par1World, par2, par4, par6);
    027    }
    028
    029    public void func_94095_a(DamageSource par1DamageSource)
    030    {
    031        super.func_94095_a(par1DamageSource);
    032
    033        for (int i = 0; i < this.getSizeInventory(); ++i)
    034        {
    035            ItemStack itemstack = this.getStackInSlot(i);
    036
    037            if (itemstack != null)
    038            {
    039                float f = this.rand.nextFloat() * 0.8F + 0.1F;
    040                float f1 = this.rand.nextFloat() * 0.8F + 0.1F;
    041                float f2 = this.rand.nextFloat() * 0.8F + 0.1F;
    042
    043                while (itemstack.stackSize > 0)
    044                {
    045                    int j = this.rand.nextInt(21) + 10;
    046
    047                    if (j > itemstack.stackSize)
    048                    {
    049                        j = itemstack.stackSize;
    050                    }
    051
    052                    itemstack.stackSize -= j;
    053                    EntityItem entityitem = new EntityItem(this.worldObj, this.posX + (double)f, this.posY + (double)f1, this.posZ + (double)f2, new ItemStack(itemstack.itemID, j, itemstack.getItemDamage()));
    054                    float f3 = 0.05F;
    055                    entityitem.motionX = (double)((float)this.rand.nextGaussian() * f3);
    056                    entityitem.motionY = (double)((float)this.rand.nextGaussian() * f3 + 0.2F);
    057                    entityitem.motionZ = (double)((float)this.rand.nextGaussian() * f3);
    058                    this.worldObj.spawnEntityInWorld(entityitem);
    059                }
    060            }
    061        }
    062    }
    063
    064    /**
    065     * Returns the stack in slot i
    066     */
    067    public ItemStack getStackInSlot(int par1)
    068    {
    069        return this.field_94113_a[par1];
    070    }
    071
    072    /**
    073     * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a
    074     * new stack.
    075     */
    076    public ItemStack decrStackSize(int par1, int par2)
    077    {
    078        if (this.field_94113_a[par1] != null)
    079        {
    080            ItemStack itemstack;
    081
    082            if (this.field_94113_a[par1].stackSize <= par2)
    083            {
    084                itemstack = this.field_94113_a[par1];
    085                this.field_94113_a[par1] = null;
    086                return itemstack;
    087            }
    088            else
    089            {
    090                itemstack = this.field_94113_a[par1].splitStack(par2);
    091
    092                if (this.field_94113_a[par1].stackSize == 0)
    093                {
    094                    this.field_94113_a[par1] = null;
    095                }
    096
    097                return itemstack;
    098            }
    099        }
    100        else
    101        {
    102            return null;
    103        }
    104    }
    105
    106    /**
    107     * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem -
    108     * like when you close a workbench GUI.
    109     */
    110    public ItemStack getStackInSlotOnClosing(int par1)
    111    {
    112        if (this.field_94113_a[par1] != null)
    113        {
    114            ItemStack itemstack = this.field_94113_a[par1];
    115            this.field_94113_a[par1] = null;
    116            return itemstack;
    117        }
    118        else
    119        {
    120            return null;
    121        }
    122    }
    123
    124    /**
    125     * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
    126     */
    127    public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
    128    {
    129        this.field_94113_a[par1] = par2ItemStack;
    130
    131        if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit())
    132        {
    133            par2ItemStack.stackSize = this.getInventoryStackLimit();
    134        }
    135    }
    136
    137    /**
    138     * Called when an the contents of an Inventory change, usually
    139     */
    140    public void onInventoryChanged() {}
    141
    142    /**
    143     * Do not make give this method the name canInteractWith because it clashes with Container
    144     */
    145    public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
    146    {
    147        return this.isDead ? false : par1EntityPlayer.getDistanceSqToEntity(this) <= 64.0D;
    148    }
    149
    150    public void openChest() {}
    151
    152    public void closeChest() {}
    153
    154    public boolean func_94041_b(int par1, ItemStack par2ItemStack)
    155    {
    156        return true;
    157    }
    158
    159    /**
    160     * Returns the name of the inventory.
    161     */
    162    public String getInvName()
    163    {
    164        return this.func_94042_c() ? this.func_95999_t() : "container.minecart";
    165    }
    166
    167    /**
    168     * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't
    169     * this more of a set than a get?*
    170     */
    171    public int getInventoryStackLimit()
    172    {
    173        return 64;
    174    }
    175
    176    /**
    177     * Teleports the entity to another dimension. Params: Dimension number to teleport to
    178     */
    179    public void travelToDimension(int par1)
    180    {
    181        this.field_94112_b = false;
    182        super.travelToDimension(par1);
    183    }
    184
    185    /**
    186     * Will get destroyed next tick.
    187     */
    188    public void setDead()
    189    {
    190        if (this.field_94112_b)
    191        {
    192            for (int i = 0; i < this.getSizeInventory(); ++i)
    193            {
    194                ItemStack itemstack = this.getStackInSlot(i);
    195
    196                if (itemstack != null)
    197                {
    198                    float f = this.rand.nextFloat() * 0.8F + 0.1F;
    199                    float f1 = this.rand.nextFloat() * 0.8F + 0.1F;
    200                    float f2 = this.rand.nextFloat() * 0.8F + 0.1F;
    201
    202                    while (itemstack.stackSize > 0)
    203                    {
    204                        int j = this.rand.nextInt(21) + 10;
    205
    206                        if (j > itemstack.stackSize)
    207                        {
    208                            j = itemstack.stackSize;
    209                        }
    210
    211                        itemstack.stackSize -= j;
    212                        EntityItem entityitem = new EntityItem(this.worldObj, this.posX + (double)f, this.posY + (double)f1, this.posZ + (double)f2, new ItemStack(itemstack.itemID, j, itemstack.getItemDamage()));
    213
    214                        if (itemstack.hasTagCompound())
    215                        {
    216                            entityitem.getEntityItem().setTagCompound((NBTTagCompound)itemstack.getTagCompound().copy());
    217                        }
    218
    219                        float f3 = 0.05F;
    220                        entityitem.motionX = (double)((float)this.rand.nextGaussian() * f3);
    221                        entityitem.motionY = (double)((float)this.rand.nextGaussian() * f3 + 0.2F);
    222                        entityitem.motionZ = (double)((float)this.rand.nextGaussian() * f3);
    223                        this.worldObj.spawnEntityInWorld(entityitem);
    224                    }
    225                }
    226            }
    227        }
    228
    229        super.setDead();
    230    }
    231
    232    /**
    233     * (abstract) Protected helper method to write subclass entity data to NBT.
    234     */
    235    protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    236    {
    237        super.writeEntityToNBT(par1NBTTagCompound);
    238        NBTTagList nbttaglist = new NBTTagList();
    239
    240        for (int i = 0; i < this.field_94113_a.length; ++i)
    241        {
    242            if (this.field_94113_a[i] != null)
    243            {
    244                NBTTagCompound nbttagcompound1 = new NBTTagCompound();
    245                nbttagcompound1.setByte("Slot", (byte)i);
    246                this.field_94113_a[i].writeToNBT(nbttagcompound1);
    247                nbttaglist.appendTag(nbttagcompound1);
    248            }
    249        }
    250
    251        par1NBTTagCompound.setTag("Items", nbttaglist);
    252    }
    253
    254    /**
    255     * (abstract) Protected helper method to read subclass entity data from NBT.
    256     */
    257    protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    258    {
    259        super.readEntityFromNBT(par1NBTTagCompound);
    260        NBTTagList nbttaglist = par1NBTTagCompound.getTagList("Items");
    261        this.field_94113_a = new ItemStack[this.getSizeInventory()];
    262
    263        for (int i = 0; i < nbttaglist.tagCount(); ++i)
    264        {
    265            NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i);
    266            int j = nbttagcompound1.getByte("Slot") & 255;
    267
    268            if (j >= 0 && j < this.field_94113_a.length)
    269            {
    270                this.field_94113_a[j] = ItemStack.loadItemStackFromNBT(nbttagcompound1);
    271            }
    272        }
    273    }
    274
    275    /**
    276     * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
    277     */
    278    public boolean interact(EntityPlayer par1EntityPlayer)
    279    {
    280        if(MinecraftForge.EVENT_BUS.post(new MinecartInteractEvent(this, par1EntityPlayer)))
    281        {
    282            return true;
    283        }
    284        if (!this.worldObj.isRemote)
    285        {
    286            par1EntityPlayer.displayGUIChest(this);
    287        }
    288
    289        return true;
    290    }
    291
    292    protected void func_94101_h()
    293    {
    294        int i = 15 - Container.func_94526_b(this);
    295        float f = 0.98F + (float)i * 0.001F;
    296        this.motionX *= (double)f;
    297        this.motionY *= 0.0D;
    298        this.motionZ *= (double)f;
    299    }
    300}