micdoodle8.mods.galacticraft.core.tile.GCCoreTileEntityTreasureChest.java Source code

Java tutorial

Introduction

Here is the source code for micdoodle8.mods.galacticraft.core.tile.GCCoreTileEntityTreasureChest.java

Source

package micdoodle8.mods.galacticraft.core.tile;

import java.util.Iterator;
import java.util.List;

import micdoodle8.mods.galacticraft.api.item.IKeyable;
import micdoodle8.mods.galacticraft.api.vector.Vector3;
import micdoodle8.mods.galacticraft.core.GalacticraftCore;
import micdoodle8.mods.galacticraft.core.blocks.GCCoreBlockT1TreasureChest;
import micdoodle8.mods.galacticraft.core.network.GCCorePacketHandlerServer.EnumPacketServer;
import micdoodle8.mods.galacticraft.core.network.GCCorePacketManager;
import micdoodle8.mods.galacticraft.core.network.IPacketReceiver;
import micdoodle8.mods.galacticraft.core.util.PacketUtil;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryLargeChest;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.Packet250CustomPayload;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.StatCollector;

import com.google.common.io.ByteArrayDataInput;

import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.network.PacketDispatcher;
import cpw.mods.fml.relauncher.Side;

/**
 * GCCoreTileEntityTreasureChest.java
 *
 * This file is part of the Galacticraft project
 *
 * @author micdoodle8
 * @license Lesser GNU Public License v3 (http://www.gnu.org/licenses/lgpl.html)
 * 
 */
public class GCCoreTileEntityTreasureChest extends TileEntity implements IInventory, IKeyable, IPacketReceiver {
    private ItemStack[] chestContents = new ItemStack[36];

    protected long ticks = 0;

    /** Determines if the check for adjacent chests has taken place. */
    public boolean adjacentChestChecked = false;

    /** Contains the chest tile located adjacent to this one (if any) */
    public GCCoreTileEntityTreasureChest adjacentChestZNeg;

    /** Contains the chest tile located adjacent to this one (if any) */
    public GCCoreTileEntityTreasureChest adjacentChestXPos;

    /** Contains the chest tile located adjacent to this one (if any) */
    public GCCoreTileEntityTreasureChest adjacentChestXNeg;

    /** Contains the chest tile located adjacent to this one (if any) */
    public GCCoreTileEntityTreasureChest adjacentChestZPos;

    /** The current angle of the lid (between 0 and 1) */
    public float lidAngle;

    /** The angle of the lid last tick */
    public float prevLidAngle;

    /** The number of players currently using this chest */
    public int numUsingPlayers;

    /** Server sync counter (once per 20 ticks) */
    private int ticksSinceSync;

    public boolean locked = true;

    public int tier = 1;

    public GCCoreTileEntityTreasureChest() {
        this(1);
    }

    public GCCoreTileEntityTreasureChest(int tier) {
        this.tier = tier;
    }

    /**
     * Returns the number of slots in the inventory.
     */
    @Override
    public int getSizeInventory() {
        return 27;
    }

    /**
     * Returns the stack in slot i
     */
    @Override
    public ItemStack getStackInSlot(int par1) {
        return this.chestContents[par1];
    }

    /**
     * Removes from an inventory slot (first arg) up to a specified number
     * (second arg) of items and returns them in a new stack.
     */
    @Override
    public ItemStack decrStackSize(int par1, int par2) {
        if (this.chestContents[par1] != null) {
            ItemStack itemstack;

            if (this.chestContents[par1].stackSize <= par2) {
                itemstack = this.chestContents[par1];
                this.chestContents[par1] = null;
                this.onInventoryChanged();
                return itemstack;
            } else {
                itemstack = this.chestContents[par1].splitStack(par2);

                if (this.chestContents[par1].stackSize == 0) {
                    this.chestContents[par1] = null;
                }

                this.onInventoryChanged();
                return itemstack;
            }
        } else {
            return null;
        }
    }

    /**
     * When some containers are closed they call this on each slot, then drop
     * whatever it returns as an EntityItem - like when you close a workbench
     * GUI.
     */
    @Override
    public ItemStack getStackInSlotOnClosing(int par1) {
        if (this.chestContents[par1] != null) {
            final ItemStack itemstack = this.chestContents[par1];
            this.chestContents[par1] = null;
            return itemstack;
        } else {
            return null;
        }
    }

    /**
     * Sets the given item stack to the specified slot in the inventory (can be
     * crafting or armor sections).
     */
    @Override
    public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
        this.chestContents[par1] = par2ItemStack;

        if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) {
            par2ItemStack.stackSize = this.getInventoryStackLimit();
        }

        this.onInventoryChanged();
    }

    /**
     * Reads a tile entity from NBT.
     */
    @Override
    public void readFromNBT(NBTTagCompound nbt) {
        super.readFromNBT(nbt);
        this.locked = nbt.getBoolean("isLocked");
        this.tier = nbt.getInteger("tier");
        final NBTTagList nbttaglist = nbt.getTagList("Items");
        this.chestContents = new ItemStack[this.getSizeInventory()];

        for (int i = 0; i < nbttaglist.tagCount(); ++i) {
            final NBTTagCompound nbttagcompound1 = (NBTTagCompound) nbttaglist.tagAt(i);
            final int j = nbttagcompound1.getByte("Slot") & 255;

            if (j >= 0 && j < this.chestContents.length) {
                this.chestContents[j] = ItemStack.loadItemStackFromNBT(nbttagcompound1);
            }
        }
    }

    /**
     * Writes a tile entity to NBT.
     */
    @Override
    public void writeToNBT(NBTTagCompound nbt) {
        super.writeToNBT(nbt);
        nbt.setBoolean("isLocked", this.locked);
        nbt.setInteger("tier", this.tier);
        final NBTTagList nbttaglist = new NBTTagList();

        for (int i = 0; i < this.chestContents.length; ++i) {
            if (this.chestContents[i] != null) {
                final NBTTagCompound nbttagcompound1 = new NBTTagCompound();
                nbttagcompound1.setByte("Slot", (byte) i);
                this.chestContents[i].writeToNBT(nbttagcompound1);
                nbttaglist.appendTag(nbttagcompound1);
            }
        }

        nbt.setTag("Items", nbttaglist);
    }

    /**
     * Returns the maximum stack size for a inventory slot. Seems to always be
     * 64, possibly will be extended. *Isn't this more of a set than a get?*
     */
    @Override
    public int getInventoryStackLimit() {
        return 64;
    }

    /**
     * Do not make give this method the name canInteractWith because it clashes
     * with Container
     */
    @Override
    public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
        return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false
                : par1EntityPlayer.getDistanceSq(this.xCoord + 0.5D, this.yCoord + 0.5D,
                        this.zCoord + 0.5D) <= 64.0D;
    }

    /**
     * Causes the TileEntity to reset all it's cached values for it's container
     * block, blockID, metaData and in the case of chests, the adjcacent chest
     * check
     */
    @Override
    public void updateContainingBlockInfo() {
        super.updateContainingBlockInfo();
        this.adjacentChestChecked = false;
    }

    private void func_90009_a(GCCoreTileEntityTreasureChest par1TileEntityChest, int par2) {
        if (par1TileEntityChest.isInvalid()) {
            this.adjacentChestChecked = false;
        } else if (this.adjacentChestChecked) {
            switch (par2) {
            case 0:
                if (this.adjacentChestZPos != par1TileEntityChest) {
                    this.adjacentChestChecked = false;
                }

                break;
            case 1:
                if (this.adjacentChestXNeg != par1TileEntityChest) {
                    this.adjacentChestChecked = false;
                }

                break;
            case 2:
                if (this.adjacentChestZNeg != par1TileEntityChest) {
                    this.adjacentChestChecked = false;
                }

                break;
            case 3:
                if (this.adjacentChestXPos != par1TileEntityChest) {
                    this.adjacentChestChecked = false;
                }
            }
        }
    }

    /**
     * Performs the check for adjacent chests to determine if this chest is
     * double or not.
     */
    public void checkForAdjacentChests() {
        if (!this.adjacentChestChecked) {
            this.adjacentChestChecked = true;
            this.adjacentChestZNeg = null;
            this.adjacentChestXPos = null;
            this.adjacentChestXNeg = null;
            this.adjacentChestZPos = null;

            if (this.func_94044_a(this.xCoord - 1, this.yCoord, this.zCoord)) {
                this.adjacentChestXNeg = (GCCoreTileEntityTreasureChest) this.worldObj
                        .getBlockTileEntity(this.xCoord - 1, this.yCoord, this.zCoord);
            }

            if (this.func_94044_a(this.xCoord + 1, this.yCoord, this.zCoord)) {
                this.adjacentChestXPos = (GCCoreTileEntityTreasureChest) this.worldObj
                        .getBlockTileEntity(this.xCoord + 1, this.yCoord, this.zCoord);
            }

            if (this.func_94044_a(this.xCoord, this.yCoord, this.zCoord - 1)) {
                this.adjacentChestZNeg = (GCCoreTileEntityTreasureChest) this.worldObj
                        .getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord - 1);
            }

            if (this.func_94044_a(this.xCoord, this.yCoord, this.zCoord + 1)) {
                this.adjacentChestZPos = (GCCoreTileEntityTreasureChest) this.worldObj
                        .getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord + 1);
            }

            if (this.adjacentChestZNeg != null) {
                this.adjacentChestZNeg.func_90009_a(this, 0);
            }

            if (this.adjacentChestZPos != null) {
                this.adjacentChestZPos.func_90009_a(this, 2);
            }

            if (this.adjacentChestXPos != null) {
                this.adjacentChestXPos.func_90009_a(this, 1);
            }

            if (this.adjacentChestXNeg != null) {
                this.adjacentChestXNeg.func_90009_a(this, 3);
            }
        }
    }

    private boolean func_94044_a(int par1, int par2, int par3) {
        final Block block = Block.blocksList[this.worldObj.getBlockId(par1, par2, par3)];
        return block != null && block instanceof GCCoreBlockT1TreasureChest;
    }

    /**
     * Allows the entity to update its state. Overridden in most subclasses,
     * e.g. the mob spawner uses this to count ticks and creates a new spawn
     * inside its implementation.
     */
    @Override
    public void updateEntity() {
        super.updateEntity();
        this.checkForAdjacentChests();
        ++this.ticksSinceSync;
        float f;

        if (!this.worldObj.isRemote && this.numUsingPlayers != 0
                && (this.ticksSinceSync + this.xCoord + this.yCoord + this.zCoord) % 200 == 0) {
            this.numUsingPlayers = 0;
            f = 5.0F;
            final List<?> list = this.worldObj.getEntitiesWithinAABB(EntityPlayer.class,
                    AxisAlignedBB.getAABBPool().getAABB(this.xCoord - f, this.yCoord - f, this.zCoord - f,
                            this.xCoord + 1 + f, this.yCoord + 1 + f, this.zCoord + 1 + f));
            final Iterator<?> iterator = list.iterator();

            while (iterator.hasNext()) {
                final EntityPlayer entityplayer = (EntityPlayer) iterator.next();

                if (entityplayer.openContainer instanceof ContainerChest) {
                    final IInventory iinventory = ((ContainerChest) entityplayer.openContainer)
                            .getLowerChestInventory();

                    if (iinventory == this || iinventory instanceof InventoryLargeChest
                            && ((InventoryLargeChest) iinventory).isPartOfLargeChest(this)) {
                        ++this.numUsingPlayers;
                    }
                }
            }
        }

        this.prevLidAngle = this.lidAngle;
        f = 0.05F;
        double d0;

        if (this.numUsingPlayers > 0 && this.lidAngle == 0.0F && this.adjacentChestZNeg == null
                && this.adjacentChestXNeg == null) {
            double d1 = this.xCoord + 0.5D;
            d0 = this.zCoord + 0.5D;

            if (this.adjacentChestZPos != null) {
                d0 += 0.5D;
            }

            if (this.adjacentChestXPos != null) {
                d1 += 0.5D;
            }

            this.worldObj.playSoundEffect(d1, this.yCoord + 0.5D, d0, "random.chestopen", 0.5F,
                    this.worldObj.rand.nextFloat() * 0.1F + 0.6F);
        }

        if (this.numUsingPlayers == 0 && this.lidAngle > 0.0F || this.numUsingPlayers > 0 && this.lidAngle < 1.0F) {
            final float f1 = this.lidAngle;

            if (this.numUsingPlayers > 0) {
                this.lidAngle += f;
            } else {
                this.lidAngle -= f;
            }

            if (this.lidAngle > 1.0F) {
                this.lidAngle = 1.0F;
            }

            final float f2 = 0.5F;

            if (this.lidAngle < f2 && f1 >= f2 && this.adjacentChestZNeg == null
                    && this.adjacentChestXNeg == null) {
                d0 = this.xCoord + 0.5D;
                double d2 = this.zCoord + 0.5D;

                if (this.adjacentChestZPos != null) {
                    d2 += 0.5D;
                }

                if (this.adjacentChestXPos != null) {
                    d0 += 0.5D;
                }

                this.worldObj.playSoundEffect(d0, this.yCoord + 0.5D, d2, "random.chestclosed", 0.5F,
                        this.worldObj.rand.nextFloat() * 0.1F + 0.6F);
            }

            if (this.lidAngle < 0.0F) {
                this.lidAngle = 0.0F;
            }
        }

        if (!this.worldObj.isRemote) {
            if (this.ticks >= Long.MAX_VALUE) {
                this.ticks = 1;
            }

            this.ticks++;

            if (this.ticks % 40 == 0) {
                GCCorePacketManager.sendPacketToClients(this.getDescriptionPacket(), this.worldObj,
                        new Vector3(this), 6);
            }
        }
    }

    @Override
    public Packet getDescriptionPacket() {
        return GCCorePacketManager.getPacket(GalacticraftCore.CHANNELENTITIES, this, this.locked);
    }

    @Override
    public void handlePacketData(INetworkManager network, int type, Packet250CustomPayload packet,
            EntityPlayer player, ByteArrayDataInput dataStream) {
        try {
            if (this.worldObj.isRemote) {
                this.locked = dataStream.readBoolean();
            }
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Called when a client event is received with the event number and
     * argument, see World.sendClientEvent
     */
    @Override
    public boolean receiveClientEvent(int par1, int par2) {
        if (par1 == 1) {
            this.numUsingPlayers = par2;
            return true;
        } else {
            return super.receiveClientEvent(par1, par2);
        }
    }

    @Override
    public void openChest() {
        if (this.numUsingPlayers < 0) {
            this.numUsingPlayers = 0;
        }

        ++this.numUsingPlayers;
        this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType().blockID, 1,
                this.numUsingPlayers);
        this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord,
                this.getBlockType().blockID);
        this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord,
                this.getBlockType().blockID);
    }

    @Override
    public void closeChest() {
        if (this.getBlockType() != null && this.getBlockType() instanceof GCCoreBlockT1TreasureChest) {
            --this.numUsingPlayers;
            this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, this.getBlockType().blockID, 1,
                    this.numUsingPlayers);
            this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord, this.zCoord,
                    this.getBlockType().blockID);
            this.worldObj.notifyBlocksOfNeighborChange(this.xCoord, this.yCoord - 1, this.zCoord,
                    this.getBlockType().blockID);
        }
    }

    @Override
    public boolean isInvNameLocalized() {
        return true;
    }

    /**
     * invalidates a tile entity
     */
    @Override
    public void invalidate() {
        super.invalidate();
        this.updateContainingBlockInfo();
        this.checkForAdjacentChests();
    }

    @Override
    public String getInvName() {
        return FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT
                ? StatCollector.translateToLocal("container.treasurechest.name")
                : StatCollector.translateToLocal("container.treasurechest.name");
    }

    @Override
    public boolean isItemValidForSlot(int par1, ItemStack par2ItemStack) {
        return true;
    }

    @Override
    public int getTierOfKeyRequired() {
        return this.tier;
    }

    @Override
    public boolean onValidKeyActivated(EntityPlayer player, ItemStack key, int face) {
        if (this.locked) {
            this.locked = false;

            if (this.worldObj.isRemote) {
                // player.playSound("galacticraft.player.unlockchest", 1.0F,
                // 1.0F);
            } else {
                if (this.adjacentChestXNeg != null) {
                    this.adjacentChestXNeg.locked = false;
                }
                if (this.adjacentChestXPos != null) {
                    this.adjacentChestXPos.locked = false;
                }
                if (this.adjacentChestZNeg != null) {
                    this.adjacentChestZNeg.locked = false;
                }
                if (this.adjacentChestZPos != null) {
                    this.adjacentChestZPos.locked = false;
                }

                if (--player.inventory.getCurrentItem().stackSize == 0) {
                    player.inventory.setInventorySlotContents(player.inventory.currentItem, null);
                }

                GCCorePacketManager.sendPacketToClients(this.getDescriptionPacket());

                if (this.adjacentChestXNeg != null) {
                    GCCorePacketManager.sendPacketToClients(this.adjacentChestXNeg.getDescriptionPacket());
                }

                if (this.adjacentChestXPos != null) {
                    GCCorePacketManager.sendPacketToClients(this.adjacentChestXPos.getDescriptionPacket());
                }

                if (this.adjacentChestZNeg != null) {
                    GCCorePacketManager.sendPacketToClients(this.adjacentChestZNeg.getDescriptionPacket());
                }

                if (this.adjacentChestZPos != null) {
                    GCCorePacketManager.sendPacketToClients(this.adjacentChestZPos.getDescriptionPacket());
                }

                return true;
            }
        }

        return false;
    }

    @Override
    public boolean onActivatedWithoutKey(EntityPlayer player, int face) {
        if (this.locked) {
            if (player.worldObj.isRemote) {
                PacketDispatcher.sendPacketToServer(PacketUtil.createPacket(GalacticraftCore.CHANNEL,
                        EnumPacketServer.ON_FAILED_CHEST_UNLOCK, new Object[] { this.getTierOfKeyRequired() }));
            }
            return true;
        }

        return false;
    }

    @Override
    public boolean canBreak() {
        return false;
    }
}