I'm having trouble finding documentation on TileEntities, I'm looking to make it so that its inventory drops on the ground when it is broken. How do you do this? Is there a method you have to override, or inherit from a specific class, or implement a specific interface? Any help would be appreciated.
First you need to ensure that the TileEntity isn't removed until after Block#getDrops is called. Look at Forge's patch to BlockFlowerPot for an example of this.
Then you need to add the TileEntity's contents to the drops list in Block#getDrops. Vanilla uses InventoryHelper#dropInventoryItems(World, BlockPos, IInventory) to drop the contents of a block's IInventory on the ground, I use this method to create a list of an IItemHandler's contents with the stacks randomly split (like the vanilla method).
If you aren't already using IItemHandler, start using it.
Rollback Post to RevisionRollBack
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
I've added the parts I've found to my Block, keeping the forge comments and putting in some test items. It seems like it now drops block if broken indirectly, but not directly by the player. Here is the code:
You're missing the World#setBlockToAir call in harvestBlock, though what you have should at least drop the item.
Put a breakpoint in each of the new methods and run Minecraft in debug mode, are they being called when you break the block?
IItemHandler is Forge's inventory API, a replacement for IInventory. Instead of implementing IInventory on your TileEntity and storing a collection of ItemStacks, you store an instance of IItemHandler and expose it via the Capability System.
The default IItemHandler implementation is ItemStackHandler, you can generally use or extend this.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
OK so I found a mod that is very similar to what I want to make, I copied some code over and now it drops the items correctly but I have some questions about it. Here is the TileEntity code:
public class TileEntitySpit extends TileEntity implements ITickable {
public int cookTimeRemaining;
public ItemStackHandler items = new ItemStackHandler(4) {
@Override
protected int getStackLimit(int slot, ItemStack stack) {
return 1;
}
// Unsure what this is for
@Override
protected void onContentsChanged(int slot) {
super.onContentsChanged(slot);
TileEntitySpit.this.markDirty();
IBlockState state = world.getBlockState(pos);
world.notifyBlockUpdate(pos, state, state, 3);
}
};
// Unsure what this is for
@Override
public SPacketUpdateTileEntity getUpdatePacket() {
NBTTagCompound tag = new NBTTagCompound();
writeToNBT(tag);
return new SPacketUpdateTileEntity(pos, 0, tag);
}
// Unsure what this is for
@Override
public NBTTagCompound getUpdateTag() {
return this.writeToNBT(new NBTTagCompound());
}
// Unsure what this is for
@Override
public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity packet) {
super.onDataPacket(net, packet);
readFromNBT(packet.getNbtCompound());
IBlockState state = world.getBlockState(pos);
world.notifyBlockUpdate(pos, state, state, 3);
}
@Override
public void update() {
}
// Capabilities
@Override
public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return true;
return super.hasCapability(capability, facing);
}
// Capabilities
@SuppressWarnings("unchecked")
@Override
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return (T) items;
return super.getCapability(capability, facing);
}
/*public boolean isUseableByPlayer(EntityPlayer player) {
return world.getTileEntity(pos) == this
&& player.getDistanceSq(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D) <= 64.0D;
}*/
@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound) {
compound = super.writeToNBT(compound);
compound.setTag("Items", items.serializeNBT());
return compound;
}
@Override
public void readFromNBT(NBTTagCompound compound) {
super.readFromNBT(compound);
items.deserializeNBT(compound.getCompoundTag("Items"));
}
public IItemHandler inventory() {
return items;
}
}
The first thing is that even though the anonymous class (I think that's what it's called) shows that the max stacksize is 1, it still accepts more than 1 item per stack. The second is the first 3 methods, one of them seems to be a packet method, but why does it need to be overridden?
It looks like if I break the block in creative, it catches at the breakpoint of removedByPlayer and then highlights the line:
if (willHarvest) return true;
I'm not sure if that means it returned or not, but that's where it stopped.
I added the setBlockToAir as well
Did you step through the code after the breakpoint was hit?
I couldn't open hoppers, is that normal?
No, that shouldn't happen. Something strange is going on.
Do you get any errors?
EDIT: Should I also try changing the code to use IItemHandler instead and do the same thing?
You should switch to IItemHandler, but that shouldn't affect this situation.
Do you have a Git repository for this mod? I can try and debug it myself.
Rollback Post to RevisionRollBack
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Hm, not exactly sure how to step through the code but I pressed the continue button and it just kept running as normal.
I didn't see any errors, but this was before I started trying to compare code from other mods and use IItemHandler, I probably should have saved a previous version but I don't have a Github for it yet so maybe I will add that if this current attempt doesn't work.
Hm, not exactly sure how to step through the code but I pressed the continue button and it just kept running as normal.
Use the Step Into, Step Over and Step Out buttons to step through the code. The documentation of your IDE's debugger should explain these in more detail.
I didn't see any errors, but this was before I started trying to compare code from other mods and use IItemHandler, I probably should have saved a previous version but I don't have a Github for it yet so maybe I will add that if this current attempt doesn't work.
You can create a local Git repository without pushing it to a remote repository like GitHub.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Huh, so it turns out that that code I found actually works perfectly, now i just need to understand a few methods. They are the ones I mentioned above, the first 3 methods and the onContentsChanged() method in the anonymous class. I think the onContentsChanged() is for updating the TileEntity, maybe for updating rendering information? But the update packet and tag methods I don't understand, my best guess is it has to do with either NBT saving or client-server stuff.
Glad I got to use breakpoints though, I had been using print statements before I probably should have started using actual debugging sooner 0_0
Huh, so it turns out that that code I found actually works perfectly, now i just need to understand a few methods. They are the ones I mentioned above, the first 3 methods and the onContentsChanged() method in the anonymous class. I think the onContentsChanged() is for updating the TileEntity, maybe for updating rendering information? But the update packet and tag methods I don't understand, my best guess is it has to do with either NBT saving or client-server stuff.
TileEntity#getUpdatePacket and TileEntity#getUpdateTag are used to sync data (e.g. inventory contents) to the client so it can be used for rendering. TileEntity#onDataPacket is called when SPacketUpdateTileEntity is received by the client, allowing you to read the data from the packet into the client-side TileEntity.
ItemStackHandler#onContentsChanged is called whenever the contents of a slot changes. TileEntity#markDirty tells Minecraft that the TileEntity's data has changed and needs to be saved. World#notifyBlockUpdate sends the TileEntity's update packet to all players watching the chunk and also tells their clients to re-render that chunk.
Rollback Post to RevisionRollBack
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
I'm having trouble finding documentation on TileEntities, I'm looking to make it so that its inventory drops on the ground when it is broken. How do you do this? Is there a method you have to override, or inherit from a specific class, or implement a specific interface? Any help would be appreciated.
First you need to ensure that the TileEntity isn't removed until after Block#getDrops is called. Look at Forge's patch to BlockFlowerPot for an example of this.
Then you need to add the TileEntity's contents to the drops list in Block#getDrops. Vanilla uses InventoryHelper#dropInventoryItems(World, BlockPos, IInventory) to drop the contents of a block's IInventory on the ground, I use this method to create a list of an IItemHandler's contents with the stacks randomly split (like the vanilla method).
If you aren't already using IItemHandler, start using it.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
I've added the parts I've found to my Block, keeping the forge comments and putting in some test items. It seems like it now drops block if broken indirectly, but not directly by the player. Here is the code:
https://pastebin.com/65RKN5vZ
What is an IItemHandler?
You're missing the World#setBlockToAir call in harvestBlock, though what you have should at least drop the item.
Put a breakpoint in each of the new methods and run Minecraft in debug mode, are they being called when you break the block?
IItemHandler is Forge's inventory API, a replacement for IInventory. Instead of implementing IInventory on your TileEntity and storing a collection of ItemStacks, you store an instance of IItemHandler and expose it via the Capability System.
The default IItemHandler implementation is ItemStackHandler, you can generally use or extend this.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
It looks like if I break the block in creative, it catches at the breakpoint of removedByPlayer and then highlights the line:
if (willHarvest) return true;
I'm not sure if that means it returned or not, but that's where it stopped.
I added the setBlockToAir as well
I couldn't open hoppers, is that normal?
EDIT: Should I also try changing the code to use IItemHandler instead and do the same thing?
OK so I found a mod that is very similar to what I want to make, I copied some code over and now it drops the items correctly but I have some questions about it. Here is the TileEntity code:
The first thing is that even though the anonymous class (I think that's what it's called) shows that the max stacksize is 1, it still accepts more than 1 item per stack. The second is the first 3 methods, one of them seems to be a packet method, but why does it need to be overridden?
Did you step through the code after the breakpoint was hit?
No, that shouldn't happen. Something strange is going on.
Do you get any errors?
You should switch to IItemHandler, but that shouldn't affect this situation.
Do you have a Git repository for this mod? I can try and debug it myself.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Hm, not exactly sure how to step through the code but I pressed the continue button and it just kept running as normal.
I didn't see any errors, but this was before I started trying to compare code from other mods and use IItemHandler, I probably should have saved a previous version but I don't have a Github for it yet so maybe I will add that if this current attempt doesn't work.
Use the Step Into, Step Over and Step Out buttons to step through the code. The documentation of your IDE's debugger should explain these in more detail.
You can create a local Git repository without pushing it to a remote repository like GitHub.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Huh, so it turns out that that code I found actually works perfectly, now i just need to understand a few methods. They are the ones I mentioned above, the first 3 methods and the onContentsChanged() method in the anonymous class. I think the onContentsChanged() is for updating the TileEntity, maybe for updating rendering information? But the update packet and tag methods I don't understand, my best guess is it has to do with either NBT saving or client-server stuff.
Glad I got to use breakpoints though, I had been using print statements before I probably should have started using actual debugging sooner 0_0
TileEntity#getUpdatePacket and TileEntity#getUpdateTag are used to sync data (e.g. inventory contents) to the client so it can be used for rendering. TileEntity#onDataPacket is called when SPacketUpdateTileEntity is received by the client, allowing you to read the data from the packet into the client-side TileEntity.
ItemStackHandler#onContentsChanged is called whenever the contents of a slot changes. TileEntity#markDirty tells Minecraft that the TileEntity's data has changed and needs to be saved. World#notifyBlockUpdate sends the TileEntity's update packet to all players watching the chunk and also tells their clients to re-render that chunk.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Ah thanks, so it was a client server thing. Well I think everything is working now, thanks for your help.