I made a tile entity, that stores RF and has 2 slots. when I put an item into one of the 2 slots, it works fine. but when I take the item out again, it starts to glitch: It appears, as the item is still in the slot, but I also have the item following my cursor. When I then place the item in my Inventory, I basically duplicated my item. but when I close the guy and open it again, the item in the slot of the tile entity disappears, because it shouldn't actually exist. I am doing TileEntity#markBlockForUpdate every tick, to sync the amount of RF with the client. When I remove this line, it works fine, but the RF doesn't update. Through that, I could trace my error back to writeToNBT/readFromNBT, but I do not know exactly why this happens. all I figured out is, that the item gets placed back into the slot by "readFromNBT" after setting it to null from IInventory#decrStackSize.
Container-Class:
public class ContainerBasicRFStorage extends Container{
public ContainerBasicRFStorage(InventoryPlayer inventory, TileEntityBasicRFStorage tileEntity) {
this.addSlotToContainer(new Slot(tileEntity, 0, 58, 18));
this.addSlotToContainer(new Slot(tileEntity, 1, 58, 56));
for (int x = 0; x < 9; ++x) {
this.addSlotToContainer(new Slot(inventory, x, 8 + x * 18, 142));
}
for (int y = 0; y < 3; ++y) {
for (int x = 0; x < 9; ++x) {
this.addSlotToContainer(new Slot(inventory, x + y * 9 + 9, 8 + x * 18, 84 + y * 18));
}
}
}
// @Override
// public void putStackInSlot(int slot, ItemStack stack) {
// if(slot == 0){
// BatterySlot aslot = (BatterySlot) this.inventorySlots.get(0);
// BatterySlot bslot = (BatterySlot) this.inventorySlots.get(1);
// aslot.setLocked(false);
// bslot.setLocked(true);
// }
// if(slot == 1){
// BatterySlot aslot = (BatterySlot) this.inventorySlots.get(0);
// BatterySlot bslot = (BatterySlot) this.inventorySlots.get(1);
// aslot.setLocked(true);
// bslot.setLocked(false);
// }
// super.putStackInSlot(slot, stack);
// }
@Override
protected boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boolean useEndIndex) {
boolean success = false;
int index = startIndex;
if (useEndIndex)
index = endIndex - 1;
Slot slot;
ItemStack stackinslot;
if (stack.isStackable()) {
while (stack.stackSize > 0 && (!useEndIndex && index < endIndex || useEndIndex && index >= startIndex)) {
slot = (Slot) this.inventorySlots.get(index);
stackinslot = slot.getStack();
if (stackinslot != null && stackinslot.getItem() == stack.getItem()
&& (!stack.getHasSubtypes() || stack.getItemDamage() == stackinslot.getItemDamage())
&& ItemStack.areItemStackTagsEqual(stack, stackinslot)) {
int l = stackinslot.stackSize + stack.stackSize;
int maxsize = Math.min(stack.getMaxStackSize(), slot.getSlotStackLimit());
if (l <= maxsize) {
stack.stackSize = 0;
stackinslot.stackSize = l;
slot.onSlotChanged();
success = true;
} else if (stackinslot.stackSize < maxsize) {
stack.stackSize -= stack.getMaxStackSize() - stackinslot.stackSize;
stackinslot.stackSize = stack.getMaxStackSize();
slot.onSlotChanged();
success = true;
}
}
if (useEndIndex) {
--index;
} else {
++index;
}
}
}
if (stack.stackSize > 0) {
if (useEndIndex) {
index = endIndex - 1;
} else {
index = startIndex;
}
while (!useEndIndex && index < endIndex || useEndIndex && index >= startIndex && stack.stackSize > 0) {
slot = (Slot) this.inventorySlots.get(index);
stackinslot = slot.getStack();
if (stackinslot == null && slot.isItemValid(stack)) {
if (stack.stackSize < slot.getSlotStackLimit()) {
slot.putStack(stack.copy());
stack.stackSize = 0;
success = true;
break;
} else {
ItemStack newstack = stack.copy();
newstack.stackSize = slot.getSlotStackLimit();
slot.putStack(newstack);
stack.stackSize -= slot.getSlotStackLimit();
success = true;
}
}
if (useEndIndex) {
--index;
} else {
++index;
}
}
}
return success;
}
@Override
public ItemStack transferStackInSlot(EntityPlayer playerIn, int fromSlot) {
ItemStack previous = null;
Slot slot = (Slot) this.inventorySlots.get(fromSlot);
if (slot != null && slot.getHasStack()) {
ItemStack current = slot.getStack();
previous = current.copy();
if (fromSlot < 2) {
if (!this.mergeItemStack(current, 2, 38, false))
return null;
} else {
if (current.getItem() == ModItems.basicBattery) {
if (!this.mergeItemStack(current, 0, 2, false))
return null;
}
}
if (current.stackSize == 0)
slot.putStack((ItemStack) null);
else
slot.onSlotChanged();
if (current.stackSize == previous.stackSize)
return null;
slot.onPickupFromSlot(playerIn, current);
}
return previous;
}
@Override
public boolean canInteractWith(EntityPlayer player) {
return true;
}
}
TileEntity-Class:
public class TileEntityBasicRFStorage extends TileEntity implements IInventory, IEnergyHandler {
public ItemStack[] slots = new ItemStack[2];
public EnergyStorage storage = new EnergyStorage(512000);
public int changedRF = 0;
int count = 0;
private int oldRF;
@Override
public void updateEntity() {
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
count++;
if (count == 20) {
count = 0;
changedRF = storage.getEnergyStored() - oldRF;
oldRF = storage.getEnergyStored();
}
transferEnergy();
super.updateEntity();
}
public void transferEnergy() {
if (storage.getEnergyStored() > 0) {
for (int i = 0; i < 6; i++) {
TileEntity entity = worldObj.getTileEntity(xCoord + (i == 0 ? 1 : 0) - (i == 1 ? 1 : 0),
yCoord + (i == 2 ? 1 : 0) - (i == 3 ? 1 : 0), zCoord + (i == 4 ? 1 : 0) - (i == 5 ? 1 : 0));
ForgeDirection dir = null;
dir = (i == 0 ? ForgeDirection.EAST : dir);
dir = (i == 1 ? ForgeDirection.WEST : dir);
dir = (i == 2 ? ForgeDirection.UP : dir);
dir = (i == 3 ? ForgeDirection.DOWN : dir);
dir = (i == 4 ? ForgeDirection.SOUTH : dir);
dir = (i == 5 ? ForgeDirection.NORTH : dir);
if (entity instanceof IEnergyReceiver) {
storage.modifyEnergyStored(-((IEnergyReceiver) entity).receiveEnergy(dir.getOpposite(),
Math.min(storage.getMaxExtract(), storage.getEnergyStored()), false));
}
}
}
}
@Override
public boolean canConnectEnergy(ForgeDirection from) {
return true;
}
@Override
public int receiveEnergy(ForgeDirection from, int maxReceive, boolean simulate) {
return storage.receiveEnergy(maxReceive, simulate);
}
@Override
public int extractEnergy(ForgeDirection from, int maxExtract, boolean simulate) {
return storage.extractEnergy(maxExtract, simulate);
}
@Override
public int getEnergyStored(ForgeDirection from) {
return storage.getEnergyStored();
}
@Override
public int getMaxEnergyStored(ForgeDirection from) {
return storage.getMaxEnergyStored();
}
@Override
public S35PacketUpdateTileEntity getDescriptionPacket() {
NBTTagCompound tagCompound = new NBTTagCompound();
this.writeToNBT(tagCompound);
S35PacketUpdateTileEntity pack = new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 0, tagCompound);
return pack;
}
@Override
public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
this.readFromNBT(pkt.func_148857_g());
}
@Override
public int getSizeInventory() {
return slots.length;
}
@Override
public ItemStack getStackInSlot(int slot) {
if (slot > getSizeInventory() || slot < 0)
return null;
return slots[slot];
}
@Override
public ItemStack decrStackSize(int slot, int count) {
if (this.getStackInSlot(slot) != null) {
ItemStack itemstack;
if (this.getStackInSlot(slot).stackSize <= count) {
itemstack = this.getStackInSlot(slot);
this.setInventorySlotContents(slot, null);
} else {
itemstack = this.getStackInSlot(slot).splitStack(count);
if (this.getStackInSlot(slot).stackSize <= 0) {
this.setInventorySlotContents(slot, null);
} else {
this.setInventorySlotContents(slot, this.getStackInSlot(slot));
}
}
this.markDirty();
return itemstack;
} else {
return null;
}
}
@Override
public ItemStack getStackInSlotOnClosing(int slot) {
ItemStack stack = this.getStackInSlot(slot);
this.setInventorySlotContents(slot, null);
return stack;
}
@Override
public void setInventorySlotContents(int slot, ItemStack stack) {
if (slot > getSizeInventory() || slot < 0)
return;
if (stack != null && stack.stackSize > this.getInventoryStackLimit())
stack.stackSize = this.getInventoryStackLimit();
if (stack != null && stack.stackSize == 0)
stack = null;
this.slots[slot] = stack;
}
@Override
public String getInventoryName() {
return "";
}
@Override
public boolean hasCustomInventoryName() {
return false;
}
@Override
public int getInventoryStackLimit() {
return 1;
}
@Override
public boolean isUseableByPlayer(EntityPlayer player) {
return true;
}
@Override
public void openInventory() {
}
@Override
public void closeInventory() {
}
@Override
public boolean isItemValidForSlot(int slot, ItemStack stack) {
return stack.getItem() == ModItems.basicBattery;
}
@Override
public void readFromNBT(NBTTagCompound tag) {
super.readFromNBT(tag);
NBTTagList list = tag.getTagList("Items", 10);
for (int i = 0; i < list.tagCount(); ++i) {
NBTTagCompound stackTag = list.getCompoundTagAt(i);
int slot = stackTag.getByte("Slot") & 255;
this.setInventorySlotContents(slot, ItemStack.loadItemStackFromNBT(stackTag));
}
storage.readFromNBT(tag);
}
@Override
public void writeToNBT(NBTTagCompound tag) {
super.writeToNBT(tag);
NBTTagList list = new NBTTagList();
for (int i = 0; i < this.getSizeInventory(); ++i) {
if (this.getStackInSlot(i) != null) {
NBTTagCompound stackTag = new NBTTagCompound();
stackTag.setByte("Slot", (byte) i);
this.getStackInSlot(i).writeToNBT(stackTag);
list.appendTag(stackTag);
}
}
tag.setTag("Items", list);
storage.writeToNBT(tag);
}
}