ironbarrels/src/main/java/cpw/mods/ironchest/TileEntityIronChest.java

602 lines
18 KiB
Java
Raw Normal View History

/*******************************************************************************
* Copyright (c) 2012 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
2016-05-19 01:47:25 +02:00
* <p>
* Contributors:
2016-05-19 01:47:25 +02:00
* cpw - initial API and implementation
******************************************************************************/
package cpw.mods.ironchest;
2016-03-21 17:44:27 +01:00
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
2016-03-21 17:44:27 +01:00
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
2016-07-04 01:56:39 +02:00
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.NetworkManager;
2016-03-21 17:44:27 +01:00
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
2016-07-04 01:56:39 +02:00
import net.minecraft.tileentity.TileEntityLockableLoot;
2014-12-02 21:25:03 +01:00
import net.minecraft.util.EnumFacing;
2015-11-23 06:34:34 +01:00
import net.minecraft.util.ITickable;
2016-03-21 17:44:27 +01:00
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraftforge.common.util.Constants;
2016-11-16 16:58:31 +01:00
import java.util.Arrays;
import java.util.Comparator;
import javax.annotation.Nullable;
public class TileEntityIronChest extends TileEntityLockableLoot implements ITickable, IInventory {
public float prevLidAngle;
public float lidAngle;
public ItemStack[] chestContents;
2016-11-16 16:58:31 +01:00
private int ticksSinceSync = -1;
private int numPlayersUsing;
private ItemStack[] topStacks;
2016-05-19 01:47:25 +02:00
private EnumFacing facing;
private boolean inventoryTouched;
private boolean hadStuff;
private String customName;
private IronChestType chestType;
2016-11-16 16:58:31 +01:00
public TileEntityIronChest () {
this(IronChestType.IRON);
}
2016-11-16 16:58:31 +01:00
protected TileEntityIronChest (IronChestType type) {
super();
this.chestType = type;
2016-05-19 01:47:25 +02:00
this.chestContents = new ItemStack[type.size];
this.topStacks = new ItemStack[8];
2016-05-19 01:47:25 +02:00
this.facing = EnumFacing.NORTH;
}
2016-11-16 16:58:31 +01:00
public void setContents (ItemStack[] contents) {
2016-05-19 01:47:25 +02:00
this.chestContents = new ItemStack[this.getType().size];
2016-11-16 16:58:31 +01:00
for (int i = 0; i < contents.length; i++) {
if (i < this.chestContents.length) {
2016-03-21 17:44:27 +01:00
this.chestContents[i] = contents[i];
2015-01-29 17:58:38 +01:00
}
}
2016-03-21 17:44:27 +01:00
this.inventoryTouched = true;
2015-01-29 17:58:38 +01:00
}
@Override
2016-11-16 16:58:31 +01:00
public int getSizeInventory () {
2016-05-19 01:47:25 +02:00
return this.chestContents.length;
}
2016-11-16 16:58:31 +01:00
public EnumFacing getFacing () {
return this.facing;
}
2016-11-16 16:58:31 +01:00
public void setFacing (EnumFacing facing) {
this.facing = facing;
}
public IronChestType getType () {
IronChestType type = IronChestType.IRON;
2016-11-16 16:58:31 +01:00
if (this.hasWorldObj()) {
IBlockState state = this.worldObj.getBlockState(this.pos);
2016-07-04 01:56:39 +02:00
2016-11-16 16:58:31 +01:00
if (state.getBlock() == IronChest.ironChestBlock) {
type = state.getValue(BlockIronChest.VARIANT_PROP);
}
}
return type;
}
@Override
2016-11-16 16:58:31 +01:00
public ItemStack getStackInSlot (int index) {
2016-07-04 01:56:39 +02:00
this.fillWithLoot((EntityPlayer) null);
2016-03-21 17:44:27 +01:00
this.inventoryTouched = true;
return this.chestContents[index];
}
@Override
2016-11-16 16:58:31 +01:00
public void markDirty () {
super.markDirty();
2016-03-21 17:44:27 +01:00
this.sortTopStacks();
}
2016-11-16 16:58:31 +01:00
protected void sortTopStacks () {
if (!this.getType().isTransparent() || (this.worldObj != null && this.worldObj.isRemote)) {
return;
}
2016-03-21 17:44:27 +01:00
ItemStack[] tempCopy = new ItemStack[this.getSizeInventory()];
boolean hasStuff = false;
int compressedIdx = 0;
2016-11-16 16:58:31 +01:00
mainLoop:
for (int i = 0; i < this.getSizeInventory(); i++) {
if (this.chestContents[i] != null) {
for (int j = 0; j < compressedIdx; j++) {
if (tempCopy[j].isItemEqual(this.chestContents[i])) {
tempCopy[j].func_190920_e(tempCopy[j].func_190916_E() + this.chestContents[i].func_190916_E());
continue mainLoop;
}
}
2016-03-21 17:44:27 +01:00
tempCopy[compressedIdx++] = this.chestContents[i].copy();
hasStuff = true;
}
}
2016-11-16 16:58:31 +01:00
if (!hasStuff && this.hadStuff) {
2016-03-21 17:44:27 +01:00
this.hadStuff = false;
2016-11-16 16:58:31 +01:00
for (int i = 0; i < this.topStacks.length; i++) {
2016-03-21 17:44:27 +01:00
this.topStacks[i] = null;
}
2016-11-16 16:58:31 +01:00
if (this.worldObj != null) {
2016-03-21 17:44:27 +01:00
IBlockState iblockstate = this.worldObj.getBlockState(this.pos);
this.worldObj.notifyBlockUpdate(this.pos, iblockstate, iblockstate, 3);
}
return;
}
2016-03-21 17:44:27 +01:00
this.hadStuff = true;
2016-03-21 17:44:27 +01:00
Arrays.sort(tempCopy, new Comparator<ItemStack>() {
@Override
2016-11-16 16:58:31 +01:00
public int compare (ItemStack o1, ItemStack o2) {
if (o1 == null) {
return 1;
2016-11-16 16:58:31 +01:00
} else if (o2 == null) {
return -1;
2016-11-16 16:58:31 +01:00
} else {
return o2.func_190916_E() - o1.func_190916_E();
}
}
});
int p = 0;
2016-11-16 16:58:31 +01:00
for (ItemStack element : tempCopy) {
if (element != ItemStack.field_190927_a && element.func_190916_E() > 0) {
2016-03-21 17:44:27 +01:00
this.topStacks[p++] = element;
2016-11-16 16:58:31 +01:00
if (p == this.topStacks.length) {
break;
}
}
}
2016-11-16 16:58:31 +01:00
for (int i = p; i < this.topStacks.length; i++) {
2016-03-21 17:44:27 +01:00
this.topStacks[i] = null;
}
2016-11-16 16:58:31 +01:00
if (this.worldObj != null) {
2016-03-21 17:44:27 +01:00
IBlockState iblockstate = this.worldObj.getBlockState(this.pos);
2016-03-21 17:44:27 +01:00
this.worldObj.notifyBlockUpdate(this.pos, iblockstate, iblockstate, 3);
}
}
@Override
2016-07-04 01:56:39 +02:00
@Nullable
2016-11-16 16:58:31 +01:00
public ItemStack decrStackSize (int index, int count) {
2016-07-04 01:56:39 +02:00
this.fillWithLoot((EntityPlayer) null);
2016-07-04 01:56:39 +02:00
ItemStack itemstack = ItemStackHelper.getAndSplit(this.chestContents, index, count);
2016-11-16 16:58:31 +01:00
if (itemstack != null) {
2016-07-04 01:56:39 +02:00
this.markDirty();
}
2016-07-04 01:56:39 +02:00
return itemstack;
}
@Override
2016-11-16 16:58:31 +01:00
public void setInventorySlotContents (int index, @Nullable ItemStack stack) {
2016-07-04 01:56:39 +02:00
this.fillWithLoot((EntityPlayer) null);
this.chestContents[index] = stack;
2016-11-16 16:58:31 +01:00
if (stack != null && stack.func_190916_E() > this.getInventoryStackLimit()) {
stack.func_190920_e(this.getInventoryStackLimit());
}
2016-03-21 17:44:27 +01:00
this.markDirty();
}
@Override
2016-11-16 16:58:31 +01:00
public String getName () {
2016-05-19 01:47:25 +02:00
return this.hasCustomName() ? this.customName : this.getType().name();
}
@Override
2016-11-16 16:58:31 +01:00
public boolean hasCustomName () {
return this.customName != null && this.customName.length() > 0;
}
2016-11-16 16:58:31 +01:00
public void setCustomName (String name) {
this.customName = name;
}
@Override
2016-11-16 16:58:31 +01:00
public void readFromNBT (NBTTagCompound compound) {
super.readFromNBT(compound);
2016-03-21 17:44:27 +01:00
this.chestContents = new ItemStack[this.getSizeInventory()];
2016-11-16 16:58:31 +01:00
if (compound.hasKey("CustomName", Constants.NBT.TAG_STRING)) {
this.customName = compound.getString("CustomName");
}
2016-11-16 16:58:31 +01:00
if (!this.checkLootAndRead(compound)) {
2016-07-04 01:56:39 +02:00
NBTTagList itemList = compound.getTagList("Items", Constants.NBT.TAG_COMPOUND);
2016-11-16 16:58:31 +01:00
for (int itemNumber = 0; itemNumber < itemList.tagCount(); ++itemNumber) {
2016-07-04 01:56:39 +02:00
NBTTagCompound item = itemList.getCompoundTagAt(itemNumber);
int slot = item.getByte("Slot") & 255;
2016-11-16 16:58:31 +01:00
if (slot >= 0 && slot < this.chestContents.length) {
2016-07-04 01:56:39 +02:00
this.chestContents[slot] = ItemStack.loadItemStackFromNBT(item);
}
}
}
this.facing = EnumFacing.VALUES[compound.getByte("facing")];
2016-03-21 17:44:27 +01:00
this.sortTopStacks();
}
@Override
2016-11-16 16:58:31 +01:00
public NBTTagCompound writeToNBT (NBTTagCompound compound) {
super.writeToNBT(compound);
2016-11-16 16:58:31 +01:00
if (!this.checkLootAndWrite(compound)) {
2016-07-04 01:56:39 +02:00
NBTTagList itemList = new NBTTagList();
2016-11-16 16:58:31 +01:00
for (int slot = 0; slot < this.chestContents.length; ++slot) {
if (this.chestContents[slot] != null) {
2016-07-04 01:56:39 +02:00
NBTTagCompound tag = new NBTTagCompound();
2016-07-04 01:56:39 +02:00
tag.setByte("Slot", (byte) slot);
2016-07-04 01:56:39 +02:00
this.chestContents[slot].writeToNBT(tag);
2016-07-04 01:56:39 +02:00
itemList.appendTag(tag);
}
}
2016-07-04 01:56:39 +02:00
compound.setTag("Items", itemList);
}
compound.setByte("facing", (byte) this.facing.ordinal());
2016-11-16 16:58:31 +01:00
if (this.hasCustomName()) {
compound.setString("CustomName", this.customName);
}
2016-05-20 00:17:38 +02:00
return compound;
}
@Override
2016-11-16 16:58:31 +01:00
public int getInventoryStackLimit () {
return 64;
}
@Override
2016-11-16 16:58:31 +01:00
public boolean isUseableByPlayer (EntityPlayer player) {
if (this.worldObj == null) {
return true;
}
2016-11-16 16:58:31 +01:00
if (this.worldObj.getTileEntity(this.pos) != this) {
return false;
}
return player.getDistanceSq(this.pos.getX() + 0.5D, this.pos.getY() + 0.5D, this.pos.getZ() + 0.5D) <= 64D;
}
@Override
2016-11-16 16:58:31 +01:00
public void update () {
// Resynchronizes clients with the server state
//@formatter:off
if (this.worldObj != null && !this.worldObj.isRemote && this.numPlayersUsing != 0 && (this.ticksSinceSync + this.pos.getX() + this.pos.getY() + this.pos.getZ()) % 200 == 0)
//@formatter:on
{
this.numPlayersUsing = 0;
float f = 5.0F;
//@formatter:off
2016-11-16 16:58:31 +01:00
for (EntityPlayer player : this.worldObj.getEntitiesWithinAABB(EntityPlayer.class,
new AxisAlignedBB(this.pos.getX() - f, this.pos.getY() - f, this.pos.getZ() - f, this.pos.getX() + 1 + f, this.pos.getY() + 1 + f, this.pos.getZ() + 1 + f)))
//@formatter:on
{
2016-11-16 16:58:31 +01:00
if (player.openContainer instanceof ContainerIronChest) {
++this.numPlayersUsing;
}
}
}
2016-11-16 16:58:31 +01:00
if (this.worldObj != null && !this.worldObj.isRemote && this.ticksSinceSync < 0) {
this.worldObj.addBlockEvent(this.pos, IronChest.ironChestBlock, 3, ((this.numPlayersUsing << 3) & 0xF8) | (this.facing.ordinal() & 0x7));
}
2016-11-16 16:58:31 +01:00
if (!this.worldObj.isRemote && this.inventoryTouched) {
2016-03-21 17:44:27 +01:00
this.inventoryTouched = false;
2016-03-21 17:44:27 +01:00
this.sortTopStacks();
}
this.ticksSinceSync++;
2016-03-21 17:44:27 +01:00
this.prevLidAngle = this.lidAngle;
float angle = 0.1F;
2016-11-16 16:58:31 +01:00
if (this.numPlayersUsing > 0 && this.lidAngle == 0.0F) {
double x = this.pos.getX() + 0.5D;
double y = this.pos.getY() + 0.5D;
double z = this.pos.getZ() + 0.5D;
//@formatter:off
this.worldObj.playSound(null, x, y, z, SoundEvents.BLOCK_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
//@formatter:on
}
2016-11-16 16:58:31 +01:00
if (this.numPlayersUsing == 0 && this.lidAngle > 0.0F || this.numPlayersUsing > 0 && this.lidAngle < 1.0F) {
float currentAngle = this.lidAngle;
2016-11-16 16:58:31 +01:00
if (this.numPlayersUsing > 0) {
this.lidAngle += angle;
2016-11-16 16:58:31 +01:00
} else {
this.lidAngle -= angle;
}
2016-11-16 16:58:31 +01:00
if (this.lidAngle > 1.0F) {
2016-03-21 17:44:27 +01:00
this.lidAngle = 1.0F;
}
float maxAngle = 0.5F;
2016-11-16 16:58:31 +01:00
if (this.lidAngle < maxAngle && currentAngle >= maxAngle) {
double x = this.pos.getX() + 0.5D;
double y = this.pos.getY() + 0.5D;
double z = this.pos.getZ() + 0.5D;
//@formatter:off
this.worldObj.playSound(null, x, y, z, SoundEvents.BLOCK_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
//@formatter:on
}
2016-11-16 16:58:31 +01:00
if (this.lidAngle < 0.0F) {
2016-03-21 17:44:27 +01:00
this.lidAngle = 0.0F;
}
}
}
@Override
2016-11-16 16:58:31 +01:00
public boolean receiveClientEvent (int id, int type) {
if (id == 1) {
this.numPlayersUsing = type;
2016-11-16 16:58:31 +01:00
} else if (id == 2) {
this.facing = EnumFacing.VALUES[type];
2016-11-16 16:58:31 +01:00
} else if (id == 3) {
this.facing = EnumFacing.VALUES[type & 0x7];
this.numPlayersUsing = (type & 0xF8) >> 3;
}
return true;
}
@Override
2016-11-16 16:58:31 +01:00
public void openInventory (EntityPlayer player) {
if (!player.isSpectator()) {
if (this.worldObj == null) {
return;
}
2016-11-16 16:58:31 +01:00
if (this.numPlayersUsing < 0) {
this.numPlayersUsing = 0;
}
2016-07-04 01:56:39 +02:00
++this.numPlayersUsing;
this.worldObj.addBlockEvent(this.pos, IronChest.ironChestBlock, 1, this.numPlayersUsing);
2016-07-04 01:56:39 +02:00
this.worldObj.notifyNeighborsOfStateChange(this.pos, IronChest.ironChestBlock);
this.worldObj.notifyNeighborsOfStateChange(this.pos.down(), IronChest.ironChestBlock);
}
}
@Override
2016-11-16 16:58:31 +01:00
public void closeInventory (EntityPlayer player) {
if (!player.isSpectator()) {
if (this.worldObj == null) {
return;
}
2016-07-04 01:56:39 +02:00
--this.numPlayersUsing;
this.worldObj.addBlockEvent(this.pos, IronChest.ironChestBlock, 1, this.numPlayersUsing);
2016-07-04 01:56:39 +02:00
this.worldObj.notifyNeighborsOfStateChange(this.pos, IronChest.ironChestBlock);
this.worldObj.notifyNeighborsOfStateChange(this.pos.down(), IronChest.ironChestBlock);
}
}
2016-11-16 16:58:31 +01:00
public ItemStack[] getTopItemStacks () {
2016-03-21 17:44:27 +01:00
return this.topStacks;
}
@Override
2016-11-16 16:58:31 +01:00
public SPacketUpdateTileEntity getUpdatePacket () {
NBTTagCompound compound = new NBTTagCompound();
2016-07-04 01:56:39 +02:00
compound.setByte("facing", (byte) this.facing.ordinal());
2016-07-04 01:56:39 +02:00
2016-03-21 17:44:27 +01:00
ItemStack[] stacks = this.buildItemStackDataList();
2016-07-04 01:56:39 +02:00
2016-11-16 16:58:31 +01:00
if (stacks != null) {
2016-07-04 01:56:39 +02:00
NBTTagList itemList = new NBTTagList();
2016-11-16 16:58:31 +01:00
for (int slot = 0; slot < stacks.length; slot++) {
if (stacks[slot] != null) {
2016-07-04 01:56:39 +02:00
NBTTagCompound item = new NBTTagCompound();
item.setByte("Slot", (byte) slot);
stacks[slot].writeToNBT(item);
itemList.appendTag(item);
}
}
2016-07-04 01:56:39 +02:00
compound.setTag("stacks", itemList);
}
return new SPacketUpdateTileEntity(this.pos, 0, compound);
}
@Override
2016-11-16 16:58:31 +01:00
public void onDataPacket (NetworkManager net, SPacketUpdateTileEntity pkt) {
if (pkt.getTileEntityType() == 0) {
NBTTagCompound compound = pkt.getNbtCompound();
this.facing = EnumFacing.VALUES[compound.getByte("facing")];
2016-07-04 01:56:39 +02:00
NBTTagList itemList = compound.getTagList("stacks", Constants.NBT.TAG_COMPOUND);
2016-03-21 17:44:27 +01:00
ItemStack[] stacks = new ItemStack[this.topStacks.length];
2016-11-16 16:58:31 +01:00
for (int item = 0; item < stacks.length; item++) {
2016-07-04 01:56:39 +02:00
NBTTagCompound itemStack = itemList.getCompoundTagAt(item);
2016-07-04 01:56:39 +02:00
int slot = itemStack.getByte("Slot") & 255;
2016-11-16 16:58:31 +01:00
if (slot >= 0 && slot < stacks.length) {
stacks[slot] = ItemStack.loadItemStackFromNBT(itemStack);
}
}
2016-11-16 16:58:31 +01:00
if (this.getType().isTransparent() && stacks != null) {
int pos = 0;
2016-11-16 16:58:31 +01:00
for (int i = 0; i < this.topStacks.length; i++) {
if (stacks[pos] != null) {
2016-03-21 17:44:27 +01:00
this.topStacks[i] = stacks[pos];
2016-11-16 16:58:31 +01:00
} else {
2016-03-21 17:44:27 +01:00
this.topStacks[i] = null;
}
pos++;
}
}
}
}
2016-11-16 16:58:31 +01:00
public ItemStack[] buildItemStackDataList () {
if (this.getType().isTransparent()) {
2016-03-21 17:44:27 +01:00
ItemStack[] sortList = new ItemStack[this.topStacks.length];
int pos = 0;
2016-11-16 16:58:31 +01:00
for (ItemStack is : this.topStacks) {
if (is != null) {
sortList[pos++] = is;
2016-11-16 16:58:31 +01:00
} else {
sortList[pos++] = null;
}
}
return sortList;
}
return null;
}
@Override
2016-07-04 01:56:39 +02:00
@Nullable
2016-11-16 16:58:31 +01:00
public ItemStack removeStackFromSlot (int index) {
2016-07-04 01:56:39 +02:00
this.fillWithLoot((EntityPlayer) null);
2016-07-04 01:56:39 +02:00
return ItemStackHelper.getAndRemove(this.chestContents, index);
}
@Override
2016-11-16 16:58:31 +01:00
public boolean isItemValidForSlot (int index, ItemStack stack) {
return this.getType().acceptsStack(stack);
}
2016-11-16 16:58:31 +01:00
public void rotateAround () {
2016-05-19 01:47:25 +02:00
this.setFacing(this.facing.rotateY());
2016-07-04 01:56:39 +02:00
2016-05-19 01:47:25 +02:00
this.worldObj.addBlockEvent(this.pos, IronChest.ironChestBlock, 2, this.facing.ordinal());
2014-12-02 21:25:03 +01:00
}
2016-11-16 16:58:31 +01:00
public void wasPlaced (EntityLivingBase entityliving, ItemStack stack) {
}
2016-11-16 16:58:31 +01:00
public void removeAdornments () {
}
@Override
2016-11-16 16:58:31 +01:00
public int getField (int id) {
return 0;
}
@Override
2016-11-16 16:58:31 +01:00
public void setField (int id, int value) {
}
@Override
2016-11-16 16:58:31 +01:00
public int getFieldCount () {
return 0;
}
@Override
2016-11-16 16:58:31 +01:00
public void clear () {
2016-07-04 01:56:39 +02:00
this.fillWithLoot((EntityPlayer) null);
2016-11-16 16:58:31 +01:00
for (int slot = 0; slot < this.chestContents.length; ++slot) {
this.chestContents[slot] = null;
}
}
@Override
2016-11-16 16:58:31 +01:00
public Container createContainer (InventoryPlayer playerInventory, EntityPlayer playerIn) {
2016-07-04 01:56:39 +02:00
this.fillWithLoot((EntityPlayer) null);
return new ContainerIronChest(playerInventory, this, this.chestType, this.chestType.xSize, this.chestType.ySize);
}
@Override
2016-11-16 16:58:31 +01:00
public String getGuiID () {
2016-05-19 01:47:25 +02:00
return "IronChest:" + this.getType().name();
}
2014-12-02 21:25:03 +01:00
@Override
2016-11-16 16:58:31 +01:00
public boolean canRenderBreaking () {
return true;
2014-12-02 21:25:03 +01:00
}
@Override
2016-11-16 16:58:31 +01:00
public NBTTagCompound getUpdateTag () {
return this.writeToNBT(new NBTTagCompound());
}
}