Items in custom inventories do not drop automatically on death, as the vanilla code only knows about vanilla inventories. If you want your inventory contents to drop on death, subscribe to the LivingDeathEvent, check if the dying entity is a player, and then iterate through all of your custom inventory slots dropping each item and setting the slot contents to null.
For items 'disappearing' between sessions, that means your inventory is either not being saved to NBT or it is not being read back from NBT. The latter often occurs due to a mismatch in the NBT key used to store the inventory, e.g. write = 'myInventory' and read = 'MyInventory'. Make sure they are the same
If it's not that, show your IExtendedEntityProperties code.
You need to use #getId() instead of #getTagType, see the tutorial demo. That's the 1.7.10 version, since you didn't specify, but if you need 1.8 just change the branch.
Yeah, very very wrong. You should NEVER store an Item-based inventory as a static reference because the inventory doesn't actually exist in the normal sense - it is recreated from NBT every time you need it.
ItemStack NBT, however, is also automatically synchronized to the client, so you should be able to access the inventory by 'creating' a new one with the ItemStack and accessing the inventory slots of THAT inventory.
Note that you should only do something like this on the client for display purposes - you cannot change anything about the inventory unless you are on the server.
Hello. Sorry to wake up this post, But I made a custom inventory, Which works, the only problem, is that the vanilla armor slots in it, arent usable.
How would I achive that?
~TNX, DrPiggy
In the tutorial, it already describes what you need to do:
// If you want, you can add ARMOR SLOTS here as well, but you need to
// make a public version of SlotArmor. I won't be doing that in this tutorial.
for (i = 0; i < 4; ++i) {
// These are the standard positions for survival inventory layout
this.addSlotToContainer(new SlotArmor(this.player, inventoryPlayer, inventoryPlayer.getSizeInventory() - 1 - i, 8, 8 + i * 18, i));
}
In the tutorial, it already describes what you need to do:
// If you want, you can add ARMOR SLOTS here as well, but you need to
// make a public version of SlotArmor. I won't be doing that in this tutorial.
for (i = 0; i < 4; ++i) {
// These are the standard positions for survival inventory layout
this.addSlotToContainer(new SlotArmor(this.player, inventoryPlayer, inventoryPlayer.getSizeInventory() - 1 - i, 8, 8 + i * 18, i));
}
The Meaning of Life, the Universe, and Everything.
Join Date:
4/10/2012
Posts:
49
Member Details
Great tutroial! Thanks a lot!
P.S. I'm very new in modding, and i need help. So i have custom player inventory with 1 slot and i have a model which i want that shows on player when certain item is equiped.
Maybe someone can explain how to do that? Or can PM me links on tutorials how to do that?
P.S. I'm very new in modding, and i need help. So i have custom player inventory with 1 slot and i have a model which i want that shows on player when certain item is equiped.
Maybe someone can explain how to do that? Or can PM me links on tutorials how to do that?
Thanks a lot!
That's a little bit more complicated, but it's possible. You'll need the following:
1. A custom message to keep the client inventory in sync with the server inventory; send this packet whenever the slot contents change
2. Subscribe to RenderPlayerEvent.Post and render your item there; take a look at some vanilla render classes to get an idea of how to render things, specifically LayerHeldItem.
Hey CoolAlias, how do I get the instance of the current item's inventory (IInventory) via the item class? I need it to be able to modify the contents of the inventory with onItemRightClick.
I'm pretty sure I showed that in the tutorial for the ItemMagicBag or whatever, but you just create a new Inventory with the stack:
ItemStack stack = player.getHeldItem(); // may also use the ItemStack from the method parameters
IInventory inventory = new InventoryMagicBag(stack); // create new inventory with the stack
inventory.setInventorySlotContents(0, new ItemStack(Items.diamond, 64)); // do something with the inventory
I'm pretty sure I showed that in the tutorial for the ItemMagicBag or whatever, but you just create a new Inventory with the stack:
ItemStack stack = player.getHeldItem(); // may also use the ItemStack from the method parameters
IInventory inventory = new InventoryMagicBag(stack); // create new inventory with the stack
inventory.setInventorySlotContents(0, new ItemStack(Items.diamond, 64)); // do something with the inventory
Isn't that creating a new instance? I tried and it doesn't work for some reason. In my case the stack already has an inventory, I just need a way to access it.
Edit: Nevermind. But I still can't get it working:
@Override
public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player)
{
if (!world.isRemote)
{
player.addChatMessage(new ChatComponentText("Inventory cleared."));
InventoryAirCannon inventory = new InventoryAirCannon(stack);
System.out.println(inventory.toString());
inventory.setInventorySlotContents(0, new ItemStack(Items.diamond, 64));
}
return stack;
}
Upon troubleshooting, I noticed that the instance that was used to display the container is different than the instance in the above code. So indeed, this creates a new instance. Perhaps my inventory constructor is incorrect?
public class InventoryAirCannon implements IInventory
{
private ItemStack[] items;
private String customName;
public InventoryAirCannon(ItemStack stack)
{
items = new ItemStack[getSizeInventory()];
if (!stack.hasTagCompound())
{
stack.setTagCompound(new NBTTagCompound());
}
readFromNBT(stack.getTagCompound());
}
public void readFromNBT(NBTTagCompound nbt)
{
NBTTagList list = nbt.getTagList("Items", NBT.TAG_COMPOUND);
items = new ItemStack[getSizeInventory()];
if (nbt.hasKey("CustomName", NBT.TAG_STRING))
{
customName = nbt.getString("CustomName");
}
for (int i = 0; i < list.tagCount(); ++i)
{
NBTTagCompound item = list.getCompoundTagAt(i);
int slot = item.getByte("Slot") & 255;
if (slot >= 0 && slot < items.length)
{
items[slot] = ItemStack.loadItemStackFromNBT(item);
}
}
}
public void writeToNBT(NBTTagCompound nbt)
{
NBTTagList list = new NBTTagList();
for (int slot = 0; slot < items.length; ++slot)
{
if (items[slot] != null)
{
NBTTagCompound item = new NBTTagCompound();
item.setByte("Slot", (byte)slot);
items[slot].writeToNBT(item);
list.appendTag(item);
}
}
nbt.setTag("Items", list);
if (hasCustomInventoryName())
{
nbt.setString("CustomName", customName);
}
}
@Override
public int getSizeInventory()
{
return 5;
}
@Override
public ItemStack getStackInSlot(int slot)
{
return items[slot];
}
@Override
public ItemStack decrStackSize(int slot, int amount)
{
if (items[slot] != null)
{
ItemStack output;
if (items[slot].stackSize <= amount)
{
output = items[slot];
items[slot] = null;
markDirty();
}
else
{
output = items[slot].splitStack(amount);
if (items[slot].stackSize == 0)
{
items[slot] = null;
}
markDirty();
}
return output;
}
else
{
return null;
}
}
@Override
public ItemStack getStackInSlotOnClosing(int slot)
{
return getStackInSlot(slot);
}
@Override
public void setInventorySlotContents(int slot, ItemStack stack)
{
items[slot] = stack;
if (items[slot] != null && items[slot].stackSize > getInventoryStackLimit())
{
items[slot].stackSize = getInventoryStackLimit();
}
markDirty();
}
@Override
public String getInventoryName()
{
return hasCustomInventoryName() ? customName : "inventory.air_cannon";
}
@Override
public boolean hasCustomInventoryName()
{
return customName != null && customName.length() > 0;
}
public void setCustomName(String name)
{
customName = name;
}
@Override
public int getInventoryStackLimit()
{
return 64;
}
@Override
public void markDirty()
{
for (int i = 0; i < getSizeInventory(); ++i)
{
if (getStackInSlot(i) != null && getStackInSlot(i).stackSize == 0)
{
setInventorySlotContents(i, null);
}
}
}
@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() instanceof ItemAirCannon);
}
}
If you set up your inventory following my tutorial, creating a new instance of the inventory is the best way to access the ItemStack as an inventory - it should automatically read the NBT tag and populate the inventory contents, etc.
If it's not working, then you probably have errors in your IInventory implementation. Show that.
If you set up your inventory following my tutorial, creating a new instance of the inventory is the best way to access the ItemStack as an inventory - it should automatically read the NBT tag and populate the inventory contents, etc.
If it's not working, then you probably have errors in your IInventory implementation. Show that.
I edited the previous post already, but here anyway:
public class InventoryAirCannon implements IInventory
{
private ItemStack[] items;
private String customName;
public InventoryAirCannon(ItemStack stack)
{
items = new ItemStack[getSizeInventory()];
if (!stack.hasTagCompound())
{
stack.setTagCompound(new NBTTagCompound());
}
readFromNBT(stack.getTagCompound());
}
public void readFromNBT(NBTTagCompound nbt)
{
NBTTagList list = nbt.getTagList("Items", NBT.TAG_COMPOUND);
items = new ItemStack[getSizeInventory()];
if (nbt.hasKey("CustomName", NBT.TAG_STRING))
{
customName = nbt.getString("CustomName");
}
for (int i = 0; i < list.tagCount(); ++i)
{
NBTTagCompound item = list.getCompoundTagAt(i);
int slot = item.getByte("Slot") & 255;
if (slot >= 0 && slot < items.length)
{
items[slot] = ItemStack.loadItemStackFromNBT(item);
}
}
}
public void writeToNBT(NBTTagCompound nbt)
{
NBTTagList list = new NBTTagList();
for (int slot = 0; slot < items.length; ++slot)
{
if (items[slot] != null)
{
NBTTagCompound item = new NBTTagCompound();
item.setByte("Slot", (byte)slot);
items[slot].writeToNBT(item);
list.appendTag(item);
}
}
nbt.setTag("Items", list);
if (hasCustomInventoryName())
{
nbt.setString("CustomName", customName);
}
}
@Override
public int getSizeInventory()
{
return 5;
}
@Override
public ItemStack getStackInSlot(int slot)
{
return items[slot];
}
@Override
public ItemStack decrStackSize(int slot, int amount)
{
if (items[slot] != null)
{
ItemStack output;
if (items[slot].stackSize <= amount)
{
output = items[slot];
items[slot] = null;
markDirty();
}
else
{
output = items[slot].splitStack(amount);
if (items[slot].stackSize == 0)
{
items[slot] = null;
}
markDirty();
}
return output;
}
else
{
return null;
}
}
@Override
public ItemStack getStackInSlotOnClosing(int slot)
{
return getStackInSlot(slot);
}
@Override
public void setInventorySlotContents(int slot, ItemStack stack)
{
items[slot] = stack;
if (items[slot] != null && items[slot].stackSize > getInventoryStackLimit())
{
items[slot].stackSize = getInventoryStackLimit();
}
markDirty();
}
@Override
public String getInventoryName()
{
return hasCustomInventoryName() ? customName : "inventory.air_cannon";
}
@Override
public boolean hasCustomInventoryName()
{
return customName != null && customName.length() > 0;
}
public void setCustomName(String name)
{
customName = name;
}
@Override
public int getInventoryStackLimit()
{
return 64;
}
@Override
public void markDirty()
{
for (int i = 0; i < getSizeInventory(); ++i)
{
if (getStackInSlot(i) != null && getStackInSlot(i).stackSize == 0)
{
setInventorySlotContents(i, null);
}
}
}
@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() instanceof ItemAirCannon);
}
}
Just followed the tutorial and I'm thinking I missed something. I have successfully saved an integer variable to my item, but am having problems with inventory saving. As it is writingToNBT, I debug and watch for changes within "tagcompound.getKeySet()". When it finally finishes and sets the tagcompound to "ItemInventory", the KeySet is increased.
I close the inventory and then reopen it. KeySet is reset to it's default when it goes into readFromNBT, -- Before the item was put into the inventory.
Thank you for the great tutorial!
Like I said, I think I'm just missing something or I'm not saving it correctly.
Looks like you're using the outdated code, e.g. saving the inventory from #onUpdate is not necessary. Also, you should never store any fields in your Item class that need to be unique per instance, such as the inventory stacks - that is impossible with Items, as there is only ONE of each.
For the most up-to-date tutorials, visit my Github page. The forum editor on this website is a right pain so I haven't fixed / updated most of my tutorials here.
I have one more question though. Is there a way I can obtain the inventory and edit that inventory from the "onUpdate" Method from within the item class? So far I have only been able to obtain the NBTTagData, which would be great if I could edit the items inside of it.
Basically, I'm needing to remove an item from the inventory from the "onUpdate" method.
If you would know how to edit the inventory from NBTTagData, that would work.
If you would know how to edit the inventory from the inventory, but from within the Item Class, that would be best.
Thanks again!
Rollback Post to RevisionRollBack
I complicate easy problems, come begging for help, and leave with a simple solution.
Items in custom inventories do not drop automatically on death, as the vanilla code only knows about vanilla inventories. If you want your inventory contents to drop on death, subscribe to the LivingDeathEvent, check if the dying entity is a player, and then iterate through all of your custom inventory slots dropping each item and setting the slot contents to null.
For items 'disappearing' between sessions, that means your inventory is either not being saved to NBT or it is not being read back from NBT. The latter often occurs due to a mismatch in the NBT key used to store the inventory, e.g. write = 'myInventory' and read = 'MyInventory'. Make sure they are the same
If it's not that, show your IExtendedEntityProperties code.
You need to use #getId() instead of #getTagType, see the tutorial demo. That's the 1.7.10 version, since you didn't specify, but if you need 1.8 just change the branch.
Yeah, very very wrong. You should NEVER store an Item-based inventory as a static reference because the inventory doesn't actually exist in the normal sense - it is recreated from NBT every time you need it.
ItemStack NBT, however, is also automatically synchronized to the client, so you should be able to access the inventory by 'creating' a new one with the ItemStack and accessing the inventory slots of THAT inventory.
Note that you should only do something like this on the client for display purposes - you cannot change anything about the inventory unless you are on the server.
Hello. Sorry to wake up this post, But I made a custom inventory, Which works, the only problem, is that the vanilla armor slots in it, arent usable.
How would I achive that?
~TNX, DrPiggy
In the tutorial, it already describes what you need to do:
Thank you very much, didn't notice
How would I make SlotArmor public? TNX
NVM - Solved it myself with some research
That's the best way to do it
Great tutroial! Thanks a lot!
P.S. I'm very new in modding, and i need help. So i have custom player inventory with 1 slot and i have a model which i want that shows on player when certain item is equiped.
Maybe someone can explain how to do that? Or can PM me links on tutorials how to do that?
Thanks a lot!
That's a little bit more complicated, but it's possible. You'll need the following:
1. A custom message to keep the client inventory in sync with the server inventory; send this packet whenever the slot contents change
2. Subscribe to RenderPlayerEvent.Post and render your item there; take a look at some vanilla render classes to get an idea of how to render things, specifically LayerHeldItem.
Hey CoolAlias, how do I get the instance of the current item's inventory (IInventory) via the item class? I need it to be able to modify the contents of the inventory with onItemRightClick.
Thanks in advance
Isn't that creating a new instance? I tried and it doesn't work for some reason.In my case the stack already has an inventory, I just need a way to access it.Edit: Nevermind. But I still can't get it working:
Upon troubleshooting, I noticed that the instance that was used to display the container is different than the instance in the above code. So indeed, this creates a new instance. Perhaps my inventory constructor is incorrect?
If you set up your inventory following my tutorial, creating a new instance of the inventory is the best way to access the ItemStack as an inventory - it should automatically read the NBT tag and populate the inventory contents, etc.
If it's not working, then you probably have errors in your IInventory implementation. Show that.
I edited the previous post already, but here anyway:
Your #markDirty implementation is incorrect - you need to make sure it writes the data to the stack's tag compound.
Alright, it finally works. Thanks for your time! Amazing how forgetting a single line can affect the functionality of the whole thing.
Just followed the tutorial and I'm thinking I missed something. I have successfully saved an integer variable to my item, but am having problems with inventory saving. As it is writingToNBT, I debug and watch for changes within "tagcompound.getKeySet()". When it finally finishes and sets the tagcompound to "ItemInventory", the KeySet is increased.
I close the inventory and then reopen it. KeySet is reset to it's default when it goes into readFromNBT, -- Before the item was put into the inventory.
Thank you for the great tutorial!
Like I said, I think I'm just missing something or I'm not saving it correctly.
--Classes that may have something to do with it--
The item: Gui opens with rightclick
http://pastebin.com/K0Fd520K
ContainerItem:
http://pastebin.com/bpNtqpzF
TunnelerInventory
http://pastebin.com/nMYz93Dv
I complicate easy problems, come begging for help, and leave with a simple solution.
Looks like you're using the outdated code, e.g. saving the inventory from #onUpdate is not necessary. Also, you should never store any fields in your Item class that need to be unique per instance, such as the inventory stacks - that is impossible with Items, as there is only ONE of each.
For the most up-to-date tutorials, visit my Github page. The forum editor on this website is a right pain so I haven't fixed / updated most of my tutorials here.
Thank you! Got it working!
I have one more question though. Is there a way I can obtain the inventory and edit that inventory from the "onUpdate" Method from within the item class? So far I have only been able to obtain the NBTTagData, which would be great if I could edit the items inside of it.
Basically, I'm needing to remove an item from the inventory from the "onUpdate" method.
If you would know how to edit the inventory from NBTTagData, that would work.
If you would know how to edit the inventory from the inventory, but from within the Item Class, that would be best.
Thanks again!
I complicate easy problems, come begging for help, and leave with a simple solution.