sunsigne Posted January 21, 2019 Share Posted January 21, 2019 (edited) Hello, I'm codding for only a week ago new, so I'm kind of nww for the moment It's been 10 hours between yesterday and today that i don't succed to find out why I don't get the content of my custom chest (yes, I make my tests on blocks called FakeBlock first ^^) when I use BreakBlock. Here is my block Spoiler package sunsigne.MyMod.blocks; import java.util.Random; import net.minecraft.block.BlockContainer; import net.minecraft.block.BlockHorizontal; import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.properties.IProperty; import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.properties.PropertyDirection; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryHelper; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumBlockRenderType; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.Mirror; import net.minecraft.util.Rotation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.Explosion; import net.minecraft.world.World; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.ItemStackHandler; import sunsigne.MyMod.IHasModel; import sunsigne.MyMod.MyMod; import sunsigne.MyMod.Reference; import sunsigne.MyMod.init.ModBlocks; import sunsigne.MyMod.init.ModItems; import sunsigne.MyMod.tileentity.FakeBlockTileEntity; public class FakeBlock extends BlockContainer implements ITileEntityProvider, IHasModel { public static final PropertyDirection FACING = BlockHorizontal.FACING; public static final int FAKE_BLOCK_GUI = 80; public FakeBlock(String name) { super(Material.ROCK); setUnlocalizedName(name); setRegistryName(name); setCreativeTab(CreativeTabs.BUILDING_BLOCKS); setSoundType(SoundType.STONE); setHardness(3.5F); setResistance(17.5F); setHarvestLevel("pickaxe", 0); setLightLevel(0.0F); //setLightOpacity(1); //setBlockUnbreakable(); ModBlocks.BLOCKS.add(this); ModItems.ITEMS.add(new ItemBlock(this).setRegistryName(this.getRegistryName())); this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH)); } @Override public void registerModels() { MyMod.proxy.registerItemRenderer(Item.getItemFromBlock(this), 0, "inventory"); } @SideOnly(Side.CLIENT) public void initModel() { ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(this), 0, new ModelResourceLocation(getRegistryName(), "inventory")); } @Override public boolean isFullBlock(IBlockState state) { return false; } @Override public boolean isFullCube(IBlockState state) { return false; } @Override public boolean isOpaqueCube(IBlockState state) { return false; } //ALL the following part is to FACE the block @Override public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state) { if (!worldIn.isRemote) { IBlockState north = worldIn.getBlockState(pos.north()); IBlockState south = worldIn.getBlockState(pos.south()); IBlockState west = worldIn.getBlockState(pos.west()); IBlockState east = worldIn.getBlockState(pos.east()); EnumFacing face = (EnumFacing)state.getValue(FACING); if (face == EnumFacing.NORTH && north.isFullBlock() && !south.isFullBlock()) face = EnumFacing.SOUTH; else if (face == EnumFacing.SOUTH && south.isFullBlock() && !north.isFullBlock()) face = EnumFacing.NORTH; else if (face == EnumFacing.WEST && west.isFullBlock() && !east.isFullBlock()) face = EnumFacing.EAST; else if (face == EnumFacing.EAST && east.isFullBlock() && !west.isFullBlock()) face = EnumFacing.WEST; worldIn.setBlockState(pos, state.withProperty(FACING, face), 2); } } @Override public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand) { return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite()); } @Override public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { worldIn.notifyBlockUpdate(pos, this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite()), state, 2); } // This override is about how the block looks, don't forget to edit it if it has animation! @Override public EnumBlockRenderType getRenderType(IBlockState state) { return EnumBlockRenderType.MODEL; } @Override public IBlockState withRotation(IBlockState state, Rotation rot) { return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING))); } @Override public IBlockState withMirror(IBlockState state, Mirror mirrorIn) { return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING))); } //I'm not sure why it is about container here ... @Override protected BlockStateContainer createBlockState() { return new BlockStateContainer(this, new IProperty[] {FACING}); } @Override public IBlockState getStateFromMeta(int meta) { EnumFacing facing = EnumFacing.getFront(meta); if(facing.getAxis() == EnumFacing.Axis.Y) facing = EnumFacing.NORTH; return this.getDefaultState().withProperty(FACING, facing); } @Override public int getMetaFromState(IBlockState state) { return ((EnumFacing)state.getValue(FACING)).getIndex(); } // End of the FACING part // Here is the CONTAINER (tileentity and gui) part @Override public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { if (worldIn.isRemote) { return true; } playerIn.openGui(MyMod.instance, Reference.FAKE_BLOCK_GUI, worldIn, pos.getX(), pos.getY(), pos.getZ()); return true; } @Override public boolean canDropFromExplosion(Explosion explosionIn) { return true; } @Override public TileEntity createNewTileEntity(World wolrdIn, int meta) { return new FakeBlockTileEntity(); } @Override public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { FakeBlockTileEntity tileentity = (FakeBlockTileEntity) worldIn.getTileEntity(pos); if (tileentity != null) { InventoryHelper.dropInventoryItems(worldIn, pos, tileentity); } super.breakBlock(worldIn, pos, state); } // End of the TILEENTITY part } Its TileEntity Spoiler package sunsigne.MyMod.tileentity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.ItemStackHelper; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityLockableLoot; import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.ItemStackHandler; import sunsigne.MyMod.Reference; import sunsigne.MyMod.container.FakeBlockContainer; public class FakeBlockTileEntity extends TileEntityLockableLoot { private NonNullList<ItemStack> fakeblockConstents = NonNullList.<ItemStack>withSize(SIZE, ItemStack.EMPTY); public static final int SIZE = 8; @Override public String getName() { return null; } @Override public boolean hasCustomName() { return false; } @Override public int getSizeInventory() { return 8; } @Override public int getInventoryStackLimit() { return 64; } @Override public boolean isEmpty() { for(ItemStack stack : this.fakeblockConstents) { if(!stack.isEmpty()) return false; } return true; } private ItemStackHandler itemStackHandler = new ItemStackHandler(SIZE) { @Override protected void onContentsChanged(int slot) { FakeBlockTileEntity.this.markDirty(); } }; @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); if (compound.hasKey("items")) { itemStackHandler.deserializeNBT((NBTTagCompound) compound.getTag("items")); } } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); compound.setTag("items", itemStackHandler.serializeNBT()); return compound; } @Override public boolean hasCapability(Capability<?> capability, EnumFacing facing) { if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return true; } return super.hasCapability(capability, facing); } @Override public <T> T getCapability(Capability<T> capability, EnumFacing facing) { if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(itemStackHandler); } return super.getCapability(capability, facing); } public boolean canInteractWith(EntityPlayer playerIn) { return !isInvalid() && playerIn.getDistanceSq(pos.add(0.5D, 0.5D, 0.5D)) <= 64D; } @Override public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn) { return new FakeBlockContainer(playerInventory, this); } @Override public String getGuiID() { return Reference.MODID + ":fake_block"; } @Override protected NonNullList<ItemStack> getItems() { return fakeblockConstents; } @Override public void openInventory(EntityPlayer player) { } @Override public void closeInventory(EntityPlayer player) { } } and its Container, even if I don't think the problem comes from it Spoiler package sunsigne.MyMod.container; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.SlotItemHandler; import sunsigne.MyMod.tileentity.FakeBlockTileEntity; public class FakeBlockContainer extends Container { private final FakeBlockTileEntity fakeblockInventory; public FakeBlockContainer(InventoryPlayer playerInventory, FakeBlockTileEntity fakeblockInventory) { this.fakeblockInventory = fakeblockInventory; addOwnSlots(); addPlayerSlots(playerInventory); } private void addPlayerSlots(InventoryPlayer playerInventory) { // Slots for the main inventory for (int row = 0; row < 3; ++row) { for (int col = 0; col < 9; ++col) { int x = 48 + col * 18; int y = row * 18 + 84; this.addSlotToContainer(new Slot(playerInventory, col + row * 9 + 10, x, y)); } } // Slots for the hotbar for (int row = 0; row < 9; ++row) { int x = 48 + row * 18; int y = 58 + 84; this.addSlotToContainer(new Slot(playerInventory, row, x, y)); } } // Here are the slots for the container itself ! private void addOwnSlots() { IItemHandler itemHandler = this.fakeblockInventory.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); this.addSlotToContainer(new SlotItemHandler(itemHandler, 0, 93, 17)); this.addSlotToContainer(new SlotItemHandler(itemHandler, 1, 111, 17)); this.addSlotToContainer(new SlotItemHandler(itemHandler, 2, 129, 17)); this.addSlotToContainer(new SlotItemHandler(itemHandler, 3, 147, 17)); this.addSlotToContainer(new SlotItemHandler(itemHandler, 4, 93, 48)); this.addSlotToContainer(new SlotItemHandler(itemHandler, 5, 111, 48)); this.addSlotToContainer(new SlotItemHandler(itemHandler, 6, 129, 48)); this.addSlotToContainer(new SlotItemHandler(itemHandler, 7, 147, 48)); } @Override public ItemStack transferStackInSlot(EntityPlayer playerIn, int index) { ItemStack itemstack = ItemStack.EMPTY; Slot slot = this.inventorySlots.get(index); if (slot != null && slot.getHasStack()) { ItemStack itemstack1 = slot.getStack(); itemstack = itemstack1.copy(); if (index < FakeBlockTileEntity.SIZE) { if (!this.mergeItemStack(itemstack1, FakeBlockTileEntity.SIZE, this.inventorySlots.size(), true)) { return ItemStack.EMPTY; } } else if (!this.mergeItemStack(itemstack1, 0, FakeBlockTileEntity.SIZE, false)) { return ItemStack.EMPTY; } if (itemstack1.isEmpty()) { slot.putStack(ItemStack.EMPTY); } else { slot.onSlotChanged(); } } return itemstack; } @Override public boolean canInteractWith(EntityPlayer playerIn) { return fakeblockInventory.canInteractWith(playerIn); } } I'm almost sure the problem comes from the way i write my items in TileEntity, but whenever I try another method my items just disseapear when I log out ^^ if anyone can help me that would be nice thank in advance Edited January 21, 2019 by sunsigne solved Quote Link to comment Share on other sites More sharing options...
Cadiboo Posted January 21, 2019 Share Posted January 21, 2019 3 hours ago, sunsigne said: private NonNullList<ItemStack> fakeblockConstents = NonNullList.<ItemStack>withSize(SIZE, ItemStack.EMPTY); public static final int SIZE = 8; Use ItemStackHandler instead of this 3 hours ago, sunsigne said: ITileEntityProvider, IHasModel Don’t do this 3 hours ago, sunsigne said: @Override public void registerModels() { MyMod.proxy.registerItemRenderer(Item.getItemFromBlock(this), 0, "inventory"); } @SideOnly(Side.CLIENT) public void initModel() { ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(this), 0, new ModelResourceLocation(getRegistryName(), "inventory")); } Don’t do this 3 hours ago, sunsigne said: FakeBlockTileEntity tileentity = (FakeBlockTileEntity) worldIn.getTileEntity(pos); if (tileentity != null) { InventoryHelper.dropInventoryItems(worldIn, pos, tileentity); } super.breakBlock(worldIn, pos, state); You should check for null before casting. What does InventoryHelper#dropInventoryItems do? Quote About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme) Link to comment Share on other sites More sharing options...
sunsigne Posted January 21, 2019 Author Share Posted January 21, 2019 (edited) 3 hours ago, Cadiboo said: Don’t do this Don’t do this You should check for null before casting It's nice to try to help me but has i spent 10 hours you can guess i already tried a lot of things and if you aren't more precise in your explanations i'll just revolve around the problem. I deleted the parts you dislike, but if i remove NonNullList from my tile entity (and everything assiociated) i just get a new problem in my FakeBlock TileEntity Spoiler package sunsigne.MyMod.tileentity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.ItemStackHelper; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityLockableLoot; import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.ItemStackHandler; import sunsigne.MyMod.Reference; import sunsigne.MyMod.container.FakeBlockContainer; public class FakeBlockTileEntity extends TileEntity { public static final int SIZE = 8; private ItemStackHandler itemStackHandler = new ItemStackHandler(SIZE) { @Override protected void onContentsChanged(int slot) { FakeBlockTileEntity.this.markDirty(); } }; @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); if (compound.hasKey("items")) { itemStackHandler.deserializeNBT((NBTTagCompound) compound.getTag("items")); } } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); compound.setTag("items", itemStackHandler.serializeNBT()); return compound; } @Override public boolean hasCapability(Capability<?> capability, EnumFacing facing) { if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return true; } return super.hasCapability(capability, facing); } @Override public <T> T getCapability(Capability<T> capability, EnumFacing facing) { if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(itemStackHandler); } return super.getCapability(capability, facing); } public boolean canInteractWith(EntityPlayer playerIn) { return !isInvalid() && playerIn.getDistanceSq(pos.add(0.5D, 0.5D, 0.5D)) <= 64D; } } FakeBlock : the problem is there Spoiler @Override public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { FakeBlockTileEntity tileentity = (FakeBlockTileEntity) worldIn.getTileEntity(pos); InventoryHelper.dropInventoryItems(worldIn, pos, tileentity); super.breakBlock(worldIn, pos, state); } Now it says "The method dropInventoryItems(World, BlockPos IInventory) in the type InventoryHelper is not applicable for the arguments (World, BlockPos, FakeBlockTileEntity). That's why I used NonNullList in the first case. Edited January 21, 2019 by sunsigne More precision Quote Link to comment Share on other sites More sharing options...
Siqhter Posted January 21, 2019 Share Posted January 21, 2019 In the breakBlock method, loop through the inventory's slots. Create a new EntityItem in the for loop and then call spawnAsEntity. I think InventoryHelper#dropInventoryItems wants an IInventory, which probably won't work in your case. This is somewhat how I did it, and I use ItemStackHandler. 1 Quote Link to comment Share on other sites More sharing options...
sunsigne Posted January 21, 2019 Author Share Posted January 21, 2019 (edited) 2 hours ago, Siqhter said: In the breakBlock method, loop through the inventory's slots. Create a new EntityItem in the for loop and then call spawnAsEntity. I think InventoryHelper#dropInventoryItems wants an IInventory, which probably won't work in your case. This is somewhat how I did it, and I use ItemStackHandler. You are my HERO ! It worked ! for curious people, here is the new BreakBlock part : Spoiler @Override public void breakBlock(World world, BlockPos pos, IBlockState state) { FakeBlockTileEntity te = (FakeBlockTileEntity) world.getTileEntity(pos); IItemHandler cap = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); for (int i = 0; i < cap.getSlots(); ++i) { ItemStack itemstack = cap.getStackInSlot(i); if (!itemstack.isEmpty()) { InventoryHelper.spawnItemStack(world, pos.getX(), pos.getY(), pos.getZ(), itemstack); } } super.breakBlock(world, pos, state); } I guess i'll never know why "dropitem" didn't work, but as lon as my items still "dropped" i don't really care ^^ Have a nice day A little (maybe stupid) question. How do i mark a topic as "solved" ? It's been 20 minutes i'm searching but not finding ^^ Edited January 21, 2019 by sunsigne How to solve a topic ? Quote Link to comment Share on other sites More sharing options...
Cadiboo Posted January 21, 2019 Share Posted January 21, 2019 You can edit your original post and add “[SOLVED] “ to the title. Here is an example of how I drop my items https://github.com/Cadiboo/WIPTechAlpha/blob/fb5883e9d76ef0361ec1ebbcb9c508611dd2ef6b/src/main/java/cadiboo/wiptech/capability/inventory/ModItemStackHandler.java#L23-L35 You still need to - Not use ITileEntityProvider: It is legacy vanilla code, simply override hasTileEntity and createTileEntity. - Not use IHasModel: It is a stupid way of registering things that makes you write the exact same lines of code for ever class, it is unneeded and a better result can be achieved with 1 single line of code. - Check for null before using the tile entity you get from world#getTileEntity - Check that the tile entity you get from world#getTileEntity actually is an instance of your tile entity before you cast it (when the block is replaced, a structure is loaded on top of it, commands like /fill, /clone or /setblock are used, or even if the server is just overloaded, it might not be an instance of your tile entity) 1 Quote About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme) Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.