I have a custom inventory that stores blocks and items during the game. However, when I save and quit and come back on, all of the blocks in the inventory were gone! Any help appreciated.
public class EventCustomInventory implements IExtendedEntityProperties,
IInventory {
private ItemStack[] inv;
public ItemStack[] armorInventory = new ItemStack[4];
/** The index of the currently held item (0-. */
public int currentItem = 0;
@SideOnly(Side.CLIENT)
/** The current ItemStack. */
private ItemStack currentItemStack;
/** The player whose inventory this is. */
public EntityPlayer player;
private ItemStack itemStack;
public EventCustomInventory() {
inv = new ItemStack[48];
}
@Override
public void saveNBTData(NBTTagCompound compound) {
NBTTagList itemList = new NBTTagList();
for (int i = 0; i < inv.length; i++) {
ItemStack stack = inv[i];
if (stack != null) {
NBTTagCompound tag = new NBTTagCompound();
tag.setByte("Slot", (byte) i);
stack.writeToNBT(tag);
itemList.appendTag(tag);
}
}
compound.setTag("Inventory", itemList);
}
@Override
public void loadNBTData(NBTTagCompound compound) {
NBTTagList tagList = compound.getTagList("Inventory");
for (int i = 0; i < tagList.tagCount(); i++) {
NBTTagCompound tag = (NBTTagCompound) tagList.tagAt(i);
byte slot = tag.getByte("Slot");
if (slot >= 0 && slot < inv.length) {
inv[slot] = ItemStack.loadItemStackFromNBT(tag);
}
}
}
@Override
public void init(Entity entity, World world) {
}
/**
* Set true whenever the inventory changes. Nothing sets it false so you
* will have to write your own code to check it and reset the value.
*/
public boolean inventoryChanged = false;
/**
* Returns the item stack currently held by the player.
*/
public ItemStack getCurrentItem() {
return this.currentItem < 9 && this.currentItem >= 0 ? this.inv[this.currentItem]
: null;
}
/**
* Get the size of the player hotbar inventory
*/
public static int getHotbarSize() {
return 9;
}
/**
* Returns a slot index in main inventory containing a specific itemID
*/
private int getInventorySlotContainItem(int par1) {
for (int j = 0; j < this.inv.length; ++j) {
if (this.inv[j] != null && this.inv[j].itemID == par1) {
return j;
}
}
return -1;
}
@SideOnly(Side.CLIENT)
private int getInventorySlotContainItemAndDamage(int par1, int par2) {
for (int k = 0; k < this.inv.length; ++k) {
if (this.inv[k] != null && this.inv[k].itemID == par1
&& this.inv[k].getItemDamage() == par2) {
return k;
}
}
return -1;
}
/**
* stores an itemstack in the users inventory
*/
private int storeItemStack(ItemStack par1ItemStack) {
for (int i = 0; i < this.inv.length; ++i) {
if (this.inv[i] != null
&& this.inv[i].itemID == par1ItemStack.itemID
&& this.inv[i].isStackable()
&& this.inv[i].stackSize < this.inv[i].getMaxStackSize()
&& this.inv[i].stackSize < this.getInventoryStackLimit()
&& (!this.inv[i].getHasSubtypes() || this.inv[i]
.getItemDamage() == par1ItemStack.getItemDamage())
&& ItemStack.areItemStackTagsEqual(this.inv[i],
par1ItemStack)) {
return i;
}
}
return -1;
}
/**
* Returns the first item stack that is empty.
*/
public int getFirstEmptyStack() {
for (int i = 0; i < this.inv.length; ++i) {
if (this.inv[i] == null) {
return i;
}
}
return -1;
}
@SideOnly(Side.CLIENT)
/**
* Sets a specific itemID as the current item being held (only if it exists on the hotbar)
*/
public void setCurrentItem(int par1, int par2, boolean par3, boolean par4) {
boolean flag2 = true;
this.currentItemStack = this.getCurrentItem();
int k;
if (par3) {
k = this.getInventorySlotContainItemAndDamage(par1, par2);
} else {
k = this.getInventorySlotContainItem(par1);
}
if (k >= 0 && k < 9) {
this.currentItem = k;
} else {
if (par4 && par1 > 0) {
int l = this.getFirstEmptyStack();
if (l >= 0 && l < 9) {
this.currentItem = l;
}
this.func_70439_a(Item.itemsList[par1], par2);
}
}
}
@SideOnly(Side.CLIENT)
/**
* Switch the current item to the next one or the previous one
*/
public void changeCurrentItem(int par1) {
if (par1 > 0) {
par1 = 1;
}
if (par1 < 0) {
par1 = -1;
}
for (this.currentItem -= par1; this.currentItem < 0; this.currentItem += 9) {
;
}
while (this.currentItem >= 9) {
this.currentItem -= 9;
}
}
/**
* Clear this player's inventory, using the specified ID and metadata as
* filters or -1 for no filter.
*/
public int clearInventory(int par1, int par2) {
int k = 0;
int l;
ItemStack itemstack;
for (l = 0; l < this.inv.length; ++l) {
itemstack = this.inv[l];
if (itemstack != null && (par1 <= -1 || itemstack.itemID == par1)
&& (par2 <= -1 || itemstack.getItemDamage() == par2)) {
k += itemstack.stackSize;
this.inv[l] = null;
}
}
for (l = 0; l < this.armorInventory.length; ++l) {
itemstack = this.armorInventory[l];
if (itemstack != null && (par1 <= -1 || itemstack.itemID == par1)
&& (par2 <= -1 || itemstack.getItemDamage() == par2)) {
k += itemstack.stackSize;
this.armorInventory[l] = null;
}
}
return k;
}
@SideOnly(Side.CLIENT)
public void func_70439_a(Item par1Item, int par2) {
if (par1Item != null) {
int j = this.getInventorySlotContainItemAndDamage(par1Item.itemID,
par2);
if (j >= 0) {
this.inv[j] = this.inv[this.currentItem];
}
if (this.currentItemStack != null
&& this.currentItemStack.isItemEnchantable()
&& this.getInventorySlotContainItemAndDamage(
this.currentItemStack.itemID,
this.currentItemStack.getItemDamageForDisplay()) == this.currentItem) {
return;
}
this.inv[this.currentItem] = new ItemStack(
Item.itemsList[par1Item.itemID], 1, par2);
}
}
/**
* This function stores as many items of an ItemStack as possible in a
* matching slot and returns the quantity of left over items.
*/
private int storePartialItemStack(ItemStack par1ItemStack) {
int i = par1ItemStack.itemID;
int j = par1ItemStack.stackSize;
int k;
if (par1ItemStack.getMaxStackSize() == 1) {
k = this.getFirstEmptyStack();
if (k < 0) {
return j;
} else {
if (this.inv[k] == null) {
this.inv[k] = ItemStack.copyItemStack(par1ItemStack);
}
return 0;
}
} else {
k = this.storeItemStack(par1ItemStack);
if (k < 0) {
k = this.getFirstEmptyStack();
}
if (k < 0) {
return j;
} else {
if (this.inv[k] == null) {
this.inv[k] = new ItemStack(i, 0,
par1ItemStack.getItemDamage());
if (par1ItemStack.hasTagCompound()) {
this.inv[k]
.setTagCompound((NBTTagCompound) par1ItemStack
.getTagCompound().copy());
}
}
int l = j;
if (j > this.inv[k].getMaxStackSize() - this.inv[k].stackSize) {
l = this.inv[k].getMaxStackSize() - this.inv[k].stackSize;
}
if (l > this.getInventoryStackLimit() - this.inv[k].stackSize) {
l = this.getInventoryStackLimit() - this.inv[k].stackSize;
}
if (l == 0) {
return j;
} else {
j -= l;
this.inv[k].stackSize += l;
this.inv[k].animationsToGo = 5;
return j;
}
}
}
}
/**
* Decrement the number of animations remaining. Only called on client side.
* This is used to handle the animation of receiving a block.
*/
public void decrementAnimations() {
for (int i = 0; i < this.inv.length; ++i) {
if (this.inv[i] != null) {
this.inv[i].updateAnimation(this.player.worldObj, this.player,
i, this.currentItem == i);
}
}
for (int i = 0; i < this.armorInventory.length; i++) {
if (this.armorInventory[i] != null) {
this.armorInventory[i].getItem().onArmorTickUpdate(
this.player.worldObj, this.player,
this.armorInventory[i]);
}
}
}
/**
* removed one item of specified itemID from inventory (if it is in a stack,
* the stack size will reduce with 1)
*/
public boolean consumeInventoryItem(int par1) {
int j = this.getInventorySlotContainItem(par1);
if (j < 0) {
return false;
} else {
if (--this.inv[j].stackSize <= 0) {
this.inv[j] = null;
}
return true;
}
}
/**
* Get if a specifiied item id is inside the inventory.
*/
public boolean hasItem(int par1) {
int j = this.getInventorySlotContainItem(par1);
return j >= 0;
}
/**
* Adds the item stack to the inventory, returns false if it is impossible.
*/
public boolean addItemStackToInventory(ItemStack par1ItemStack) {
if (par1ItemStack == null) {
return false;
} else {
try {
int i;
if (par1ItemStack.isItemDamaged()) {
i = this.getFirstEmptyStack();
if (i >= 0) {
this.inv[i] = ItemStack.copyItemStack(par1ItemStack);
this.inv[i].animationsToGo = 5;
par1ItemStack.stackSize = 0;
return true;
} else {
return false;
}
} else {
do {
i = par1ItemStack.stackSize;
par1ItemStack.stackSize = this
.storePartialItemStack(par1ItemStack);
} while (par1ItemStack.stackSize > 0
&& par1ItemStack.stackSize < i);
}
return par1ItemStack.stackSize < i;
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.makeCrashReport(
throwable, "Adding item to inventory");
CrashReportCategory crashreportcategory = crashreport
.makeCategory("Item being added");
crashreportcategory.addCrashSection("Item ID",
Integer.valueOf(par1ItemStack.itemID));
crashreportcategory.addCrashSection("Item data",
Integer.valueOf(par1ItemStack.getItemDamage()));
throw new ReportedException(crashreport);
}
}
}
/**
* Removes from an inventory slot (first arg) up to a specified number
* (second arg) of items and returns them in a new stack.
*/
public ItemStack decrStackSize(int par1, int par2) {
ItemStack[] aitemstack = this.inv;
if (par1 >= this.inv.length) {
aitemstack = this.armorInventory;
par1 -= this.inv.length;
}
if (aitemstack[par1] != null) {
ItemStack itemstack;
if (aitemstack[par1].stackSize <= par2) {
itemstack = aitemstack[par1];
aitemstack[par1] = null;
return itemstack;
} else {
itemstack = aitemstack[par1].splitStack(par2);
if (aitemstack[par1].stackSize == 0) {
aitemstack[par1] = null;
}
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.
*/
public ItemStack getStackInSlotOnClosing(int par1) {
ItemStack[] aitemstack = this.inv;
if (par1 >= this.inv.length) {
aitemstack = this.armorInventory;
par1 -= this.inv.length;
}
if (aitemstack[par1] != null) {
ItemStack itemstack = aitemstack[par1];
aitemstack[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).
*/
public void setInventorySlotContents(int par1, ItemStack par2ItemStack) {
ItemStack[] aitemstack = this.inv;
if (par1 >= aitemstack.length) {
par1 -= aitemstack.length;
aitemstack = this.armorInventory;
}
aitemstack[par1] = par2ItemStack;
}
/**
* Gets the strength of the current item (tool) against the specified block,
* 1.0f if not holding anything.
*/
public float getStrVsBlock(Block par1Block) {
float f = 1.0F;
if (this.inv[this.currentItem] != null) {
f *= this.inv[this.currentItem].getStrVsBlock(par1Block);
}
return f;
}
/**
* Returns the number of slots in the inventory.
*/
public int getSizeInventory() {
return this.inv.length;
}
/**
* Returns the stack in slot i
*/
public ItemStack getStackInSlot(int par1) {
ItemStack[] aitemstack = this.inv;
if (par1 >= aitemstack.length) {
par1 -= aitemstack.length;
aitemstack = this.armorInventory;
}
return aitemstack[par1];
}
/**
* Returns the name of the inventory.
*/
public String getInvName() {
return "CustomInventory";
}
/**
* If this returns false, the inventory name will be used as an unlocalized
* name, and translated into the player's language. Otherwise it will be
* used directly.
*/
public boolean isInvNameLocalized() {
return false;
}
/**
* 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?*
*/
public int getInventoryStackLimit() {
return 64;
}
/**
* Return damage vs an entity done by the current held weapon, or 1 if
* nothing is held
*/
public int getDamageVsEntity(Entity par1Entity) {
ItemStack itemstack = this.getStackInSlot(this.currentItem);
return itemstack != null ? itemstack.getDamageVsEntity(par1Entity) : 1;
}
/**
* Returns whether the current item (tool) can harvest from the specified
* block (actually get a result).
*/
public boolean canHarvestBlock(Block par1Block) {
if (par1Block.blockMaterial.isToolNotRequired()) {
return true;
} else {
ItemStack itemstack = this.getStackInSlot(this.currentItem);
return itemstack != null ? itemstack.canHarvestBlock(par1Block)
: false;
}
}
/**
* returns a player armor item (as itemstack) contained in specified armor
* slot.
*/
public ItemStack armorItemInSlot(int par1) {
return this.armorInventory[par1];
}
/**
* Based on the damage values and maximum damage values of each armor item,
* returns the current armor value.
*/
public int getTotalArmorValue() {
int i = 0;
for (int j = 0; j < this.armorInventory.length; ++j) {
if (this.armorInventory[j] != null
&& this.armorInventory[j].getItem() instanceof ItemArmor) {
int k = ((ItemArmor) this.armorInventory[j].getItem()).damageReduceAmount;
i += k;
}
}
return i;
}
/**
* Damages armor in each slot by the specified amount.
*/
public void damageArmor(int par1) {
par1 /= 4;
if (par1 < 1) {
par1 = 1;
}
for (int j = 0; j < this.armorInventory.length; ++j) {
if (this.armorInventory[j] != null
&& this.armorInventory[j].getItem() instanceof ItemArmor) {
this.armorInventory[j].damageItem(par1, this.player);
if (this.armorInventory[j].stackSize == 0) {
this.armorInventory[j] = null;
}
}
}
}
/**
* Drop all armor and main inventory items.
*/
public void dropAllItems() {
int i;
for (i = 0; i < this.inv.length; ++i) {
if (this.inv[i] != null) {
this.player.dropPlayerItemWithRandomChoice(this.inv[i], true);
this.inv[i] = null;
}
}
for (i = 0; i < this.armorInventory.length; ++i) {
if (this.armorInventory[i] != null) {
this.player.dropPlayerItemWithRandomChoice(
this.armorInventory[i], true);
this.armorInventory[i] = null;
}
}
}
/**
* Called when an the contents of an Inventory change, usually
*/
public void onInventoryChanged() {
this.inventoryChanged = true;
}
public void setItemStack(ItemStack par1ItemStack) {
this.itemStack = par1ItemStack;
}
public ItemStack getItemStack() {
return this.itemStack;
}
/**
* Do not make give this method the name canInteractWith because it clashes
* with Container
*/
public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) {
return this.player.isDead ? false : par1EntityPlayer
.getDistanceSqToEntity(this.player) <= 64.0D;
}
/**
* Returns true if the specified ItemStack exists in the inventory.
*/
public boolean hasItemStack(ItemStack par1ItemStack) {
int i;
for (i = 0; i < this.armorInventory.length; ++i) {
if (this.armorInventory[i] != null
&& this.armorInventory[i].isItemEqual(par1ItemStack)) {
return true;
}
}
for (i = 0; i < this.inv.length; ++i) {
if (this.inv[i] != null && this.inv[i].isItemEqual(par1ItemStack)) {
return true;
}
}
return false;
}
public void openChest() {
}
public void closeChest() {
}
/**
* Returns true if automation is allowed to insert the given stack (ignoring
* stack size) into the given slot.
*/
public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) {
return true;
}
/**
* Copy the ItemStack contents from another InventoryPlayer instance
*/
public void copyInventory(EventCustomInventory par1InventoryPlayer) {
int i;
for (i = 0; i < this.inv.length; ++i) {
this.inv[i] = ItemStack.copyItemStack(par1InventoryPlayer.inv[i]);
}
for (i = 0; i < this.armorInventory.length; ++i) {
this.armorInventory[i] = ItemStack
.copyItemStack(par1InventoryPlayer.armorInventory[i]);
}
this.currentItem = par1InventoryPlayer.currentItem;
}
}
Edit: Found the Solution. The NBT tag names should be changed so they arent those of the vanilla inventory.