Posted March 8, 201510 yr I've been looking through the EntityItemFrame class to try to get a clue as to how MC displays an item that's stored in the frame. I have a Shelf block that acts as a container for four item stacks and I'd like to display a single item that represents each stack on the shelf at a specific location in the cube. I can't seem to find which methods are used to actually display the item in Item Frames, and I'm not even sure I can use the same method. Does anyone know how to do this like Item Frames do, or a better way? Here's my shelf title entity: package com.rosecotton.shelvesmod; import java.util.Arrays; import net.minecraft.block.BlockChest; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; //import net.minecraft.network.INetworkManager; import net.minecraft.network.Packet; //import net.minecraft.network.packet.Packet132TileEntityData; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.IChatComponent; import net.minecraft.world.World; import net.minecraft.nbt.NBTTagList; public class ShelfTitleEntity extends TileEntity implements IInventory { final int NUMBER_OF_SLOTS = 4; public int numPlayersUsing; private ItemStack[] itemStacks = new ItemStack[NUMBER_OF_SLOTS]; // will add a key for this container to the lang file so we can name it in the GUI @Override public String getName() { return "Block Shelf"; } @Override public boolean hasCustomName() { return false; } // standard code to look up what the human-readable name is @Override public IChatComponent getDisplayName() { return this.hasCustomName() ? new ChatComponentText(this.getName()) : new ChatComponentTranslation(this.getName()); } @Override public int getSizeInventory() { return itemStacks.length; } @Override public ItemStack getStackInSlot(int slotIndex) { return itemStacks[slotIndex]; } @Override public ItemStack decrStackSize(int slotIndex, int count) { ItemStack itemStackInSlot = getStackInSlot(slotIndex); if (itemStackInSlot == null) return null; ItemStack itemStackRemoved; if (itemStackInSlot.stackSize <= count) { itemStackRemoved = itemStackInSlot; setInventorySlotContents(slotIndex, null); } else { itemStackRemoved = itemStackInSlot.splitStack(count); if (itemStackInSlot.stackSize == 0) { setInventorySlotContents(slotIndex, null); } } markDirty(); return itemStackRemoved; } // ----------------------------------------------------------------------------------------------------------- // The following method is not needed for this example but are part of IInventory so must be implemented /** * This method removes the entire contents of the given slot and returns it. * Used by containers such as crafting tables which return any items in their slots when you close the GUI * @param slotIndex * @return */ @Override public ItemStack getStackInSlotOnClosing(int slotIndex) { ItemStack itemStack = getStackInSlot(slotIndex); if (itemStack != null) setInventorySlotContents(slotIndex, null); return itemStack; } // overwrites the stack in the given slotIndex with the given stack @Override public void setInventorySlotContents(int slotIndex, ItemStack itemstack) { itemStacks[slotIndex] = itemstack; if (itemstack != null && itemstack.stackSize > getInventoryStackLimit()) { itemstack.stackSize = getInventoryStackLimit(); } markDirty(); } // This is the maximum number if items allowed in each slot // This only affects things such as hoppers trying to insert items you need to use the container to enforce this for players // inserting items via the gui @Override public int getInventoryStackLimit() { return 64; } // Return true if the given player is able to use this block. In this case it checks that // 1) the world tileentity hasn't been replaced in the meantime, and // 2) the player isn't too far away from the centre of the block @Override public boolean isUseableByPlayer(EntityPlayer player) { if (this.worldObj.getTileEntity(this.pos) != this) return false; final double X_CENTRE_OFFSET = 0.5; final double Y_CENTRE_OFFSET = 0.5; final double Z_CENTRE_OFFSET = 0.5; final double MAXIMUM_DISTANCE_SQ = 8.0 * 8.0; return player.getDistanceSq(pos.getX() + X_CENTRE_OFFSET, pos.getY() + Y_CENTRE_OFFSET, pos.getZ() + Z_CENTRE_OFFSET) < MAXIMUM_DISTANCE_SQ; } //----------------------------------------------------------------------------------------------------------- //The following method is not needed for this example but are part of IInventory so must be implemented @Override public void openInventory(EntityPlayer player) { if (!player.isSpectator()) { if (this.numPlayersUsing < 0) { this.numPlayersUsing = 0; } ++this.numPlayersUsing; this.worldObj.addBlockEvent(this.pos, this.getBlockType(), 1, this.numPlayersUsing); this.worldObj.notifyNeighborsOfStateChange(this.pos, this.getBlockType()); this.worldObj.notifyNeighborsOfStateChange(this.pos.down(), this.getBlockType()); System.out.println("Called method: ShelfTitleEntity.openInventory"); } } //----------------------------------------------------------------------------------------------------------- //The following method is not needed for this example but are part of IInventory so must be implemented @Override public void closeInventory(EntityPlayer player) { if (!player.isSpectator() && this.getBlockType() instanceof BlockChest) { --this.numPlayersUsing; this.worldObj.addBlockEvent(this.pos, this.getBlockType(), 1, this.numPlayersUsing); this.worldObj.notifyNeighborsOfStateChange(this.pos, this.getBlockType()); this.worldObj.notifyNeighborsOfStateChange(this.pos.down(), this.getBlockType()); } } // Return true if the given stack is allowed to go in the given slot. In this case, we can insert anything. // This only affects things such as hoppers trying to insert items you need to use the container to enforce this for players // inserting items via the gui @Override public boolean isItemValidForSlot(int slotIndex, ItemStack itemstack) { return true; } // This is where you save any data that you don't want to lose when the tile entity unloads // In this case, it saves the itemstacks stored in the container @Override public void writeToNBT(NBTTagCompound parentNBTTagCompound) { super.writeToNBT(parentNBTTagCompound); // The super call is required to save and load the tileEntity's location // to use an analogy with Java, this code generates an array of hashmaps // The itemStack in each slot is converted to an NBTTagCompound, which is effectively a hashmap of key->value pairs such // as slot=1, id=2353, count=1, etc // Each of these NBTTagCompound are then inserted into NBTTagList, which is similar to an array. NBTTagList dataForAllSlots = new NBTTagList(); for (int i = 0; i < this.itemStacks.length; ++i) { if (this.itemStacks[i] != null) { NBTTagCompound dataForThisSlot = new NBTTagCompound(); dataForThisSlot.setByte("Slot", (byte) i); this.itemStacks[i].writeToNBT(dataForThisSlot); dataForAllSlots.appendTag(dataForThisSlot); } } // the array of hashmaps is then inserted into the parent hashmap for the container parentNBTTagCompound.setTag("Items", dataForAllSlots); } // This is where you load the data that you saved in writeToNBT @Override public void readFromNBT(NBTTagCompound parentNBTTagCompound) { super.readFromNBT(parentNBTTagCompound); // The super call is required to save and load the tiles location final byte NBT_TYPE_COMPOUND = 10; // See NBTBase.createNewByType() for a listing NBTTagList dataForAllSlots = parentNBTTagCompound.getTagList("Items", NBT_TYPE_COMPOUND); Arrays.fill(itemStacks, null); // set all slots to empty for (int i = 0; i < dataForAllSlots.tagCount(); ++i) { NBTTagCompound dataForOneSlot = dataForAllSlots.getCompoundTagAt(i); int slotIndex = dataForOneSlot.getByte("Slot") & 255; if (slotIndex >= 0 && slotIndex < this.itemStacks.length) { this.itemStacks[slotIndex] = ItemStack.loadItemStackFromNBT(dataForOneSlot); } } } public boolean receiveClientEvent(int id, int type) { if (id == 1) { this.numPlayersUsing = type; return true; } else { return super.receiveClientEvent(id, type); } } @Override public int getField(int id) { return Item.getIdFromItem(itemStacks[id].getItem()); } @Override public void setField(int id, int value) { itemStacks[id].setItem(Item.getItemById(value)); } @Override public int getFieldCount() { return itemStacks.length; } // set all slots to empty @Override public void clear() { Arrays.fill(itemStacks, null); } } package com.rosecotton.shelvesmod; //import BlockStairs; import java.util.Iterator; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; import net.minecraft.block.properties.IProperty; import net.minecraft.block.properties.PropertyDirection; import net.minecraft.block.properties.PropertyEnum; import net.minecraft.block.state.BlockState; import net.minecraft.block.state.IBlockState; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.passive.EntityOcelot; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryHelper; import net.minecraft.inventory.InventoryLargeChest; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityChest; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.BlockPos; import net.minecraft.util.EnumFacing; import net.minecraft.util.IStringSerializable; import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.ILockableContainer; import net.minecraft.world.World; import net.minecraftforge.fml.common.registry.GameRegistry; public class BlockShelf extends BlockContainer { public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL); public static final PropertyEnum SECTION = PropertyEnum.create("section", BlockShelf.EnumShape.class); private final Random rand = new Random(); // private static final String __OBFID = "CL_00000214"; private final String name = "shelfBlock"; ModelResourceLocation modelresourcelocation = new ModelResourceLocation("shelvesmod"+":"+name, "inventory"); protected BlockShelf(int type) { super(Material.wood); //TEH FOLLOWIONG LINE MIGHT HAVE BEEN USEFUL BUT MAYBE CAUSED AN ERROR AT RUNTIME, TRY AGAIN this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH)); //this.chestType = type; this.setCreativeTab(CreativeTabs.tabMisc); this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F); this.useNeighborBrightness = true; this.setDefaultState(this.blockState.getBaseState()); GameRegistry.registerBlock(this, name); this.setUnlocalizedName(ShelvesMod.MODID + "_" + name); this.setBlockBounds(1/16.0F, 0, 1/16.0F, 15/16.0F, 8/16.0F, 15/16.0F); } public String toString() { return this.name; } public String getName() { return this.name; } // used by the renderer to control lighting and visibility of other blocks. // set to false because this block doesn't fill the entire 1x1x1 space @Override public boolean isOpaqueCube() { return false; } // used by the renderer to control lighting and visibility of other blocks, also by // (eg) wall or fence to control whether the fence joins itself to this block // set to false because this block doesn't fill the entire 1x1x1 space @Override public boolean isFullCube() { return false; } // this function returns the correct item type corresponding to the colour of our block; // i.e. when a sign is broken, it will drop the correct item. @Override public int damageDropped(IBlockState state) { //EnumColour enumColour = (EnumColour)state.getValue(PROPERTYCOLOUR); //return this.getMetadata();//enumColour.getMetadata(); return 0; } public void setBlockBoundsBasedOnState(IBlockAccess worldIn, BlockPos pos) { if (worldIn.getBlockState(pos.north()).getBlock() == this) { this.setBlockBounds(0.0625F, 0.0F, 0.0F, 0.9375F, 0.875F, 0.9375F); } else if (worldIn.getBlockState(pos.south()).getBlock() == this) { this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 1.0F); } else if (worldIn.getBlockState(pos.west()).getBlock() == this) { this.setBlockBounds(0.0F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F); } else if (worldIn.getBlockState(pos.east()).getBlock() == this) { this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 1.0F, 0.875F, 0.9375F); } else { this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F); } } public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state) { //this.checkForSurroundingChests(worldIn, pos, state); Iterator iterator = EnumFacing.Plane.HORIZONTAL.iterator(); while (iterator.hasNext()) { EnumFacing enumfacing = (EnumFacing)iterator.next(); BlockPos blockpos1 = pos.offset(enumfacing); IBlockState iblockstate1 = worldIn.getBlockState(blockpos1); } } @Override public IBlockState onBlockPlaced(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase player) { return this.getDefaultState().withProperty(FACING, player.getHorizontalFacing()); } public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { EnumFacing enumfacing = EnumFacing.getHorizontal(MathHelper.floor_double((double)(placer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3).getOpposite(); state = state.withProperty(FACING, enumfacing); BlockPos blockpos1 = pos.north(); BlockPos blockpos2 = pos.south(); BlockPos blockpos3 = pos.west(); BlockPos blockpos4 = pos.east(); boolean flag = this == worldIn.getBlockState(blockpos1).getBlock(); boolean flag1 = this == worldIn.getBlockState(blockpos2).getBlock(); boolean flag2 = this == worldIn.getBlockState(blockpos3).getBlock(); boolean flag3 = this == worldIn.getBlockState(blockpos4).getBlock(); if (!flag && !flag1 && !flag2 && !flag3) { worldIn.setBlockState(pos, state, 3); } else if (enumfacing.getAxis() == EnumFacing.Axis.X && (flag || flag1)) { if (flag) { worldIn.setBlockState(blockpos1, state, 3); } else { worldIn.setBlockState(blockpos2, state, 3); } worldIn.setBlockState(pos, state, 3); } else if (enumfacing.getAxis() == EnumFacing.Axis.Z && (flag2 || flag3)) { if (flag2) { worldIn.setBlockState(blockpos3, state, 3); } else { worldIn.setBlockState(blockpos4, state, 3); } worldIn.setBlockState(pos, state, 3); } if (stack.hasDisplayName()) { TileEntity tileentity = worldIn.getTileEntity(pos); if (tileentity instanceof TileEntityChest) { ((TileEntityChest)tileentity).setCustomName(stack.getDisplayName()); } } } public IBlockState correctFacing(World worldIn, BlockPos pos, IBlockState state) { EnumFacing enumfacing = null; Iterator iterator = EnumFacing.Plane.HORIZONTAL.iterator(); while (iterator.hasNext()) { EnumFacing enumfacing1 = (EnumFacing)iterator.next(); IBlockState iblockstate1 = worldIn.getBlockState(pos.offset(enumfacing1)); if (iblockstate1.getBlock() == this) { return state; } if (iblockstate1.getBlock().isFullBlock()) { if (enumfacing != null) { enumfacing = null; break; } enumfacing = enumfacing1; } } if (enumfacing != null) { return state.withProperty(FACING, enumfacing.getOpposite()); } else { EnumFacing enumfacing2 = (EnumFacing)state.getValue(FACING); if (worldIn.getBlockState(pos.offset(enumfacing2)).getBlock().isFullBlock()) { enumfacing2 = enumfacing2.getOpposite(); } if (worldIn.getBlockState(pos.offset(enumfacing2)).getBlock().isFullBlock()) { enumfacing2 = enumfacing2.rotateY(); } if (worldIn.getBlockState(pos.offset(enumfacing2)).getBlock().isFullBlock()) { enumfacing2 = enumfacing2.getOpposite(); } return state.withProperty(FACING, enumfacing2); } } public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { TileEntity tileentity = worldIn.getTileEntity(pos); if (tileentity instanceof IInventory) { InventoryHelper.dropInventoryItems(worldIn, pos, (IInventory)tileentity); worldIn.updateComparatorOutputLevel(pos, this); } super.breakBlock(worldIn, pos, state); } /* // This is where you can do something when the block is broken. In this case drop the inventory's contents @Override public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { IInventory inventory = worldIn.getTileEntity(pos) instanceof IInventory ? (IInventory)worldIn.getTileEntity(pos) : null; if (inventory != null){ // For each slot in the inventory for (int i = 0; i < inventory.getSizeInventory(); i++){ // If the slot is not empty if (inventory.getStackInSlot(i) != null) { // Create a new entity item with the item stack in the slot EntityItem item = new EntityItem(worldIn, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, inventory.getStackInSlot(i)); // Apply some random motion to the item float multiplier = 0.1f; float motionX = worldIn.rand.nextFloat() - 0.5f; float motionY = worldIn.rand.nextFloat() - 0.5f; float motionZ = worldIn.rand.nextFloat() - 0.5f; item.motionX = motionX * multiplier; item.motionY = motionY * multiplier; item.motionZ = motionZ * multiplier; // Spawn the item in the world worldIn.spawnEntityInWorld(item); } } // Clear the inventory so nothing else (such as another mod) can do anything with the items inventory.clear(); } // Super MUST be called last because it removes the tile entity super.breakBlock(worldIn, pos, state); }*/ // Called when the block is right clicked // In this block it is used to open the blocks gui when right clicked by a player @Override public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumFacing side, float hitX, float hitY, float hitZ) { // Uses the gui handler registered to your mod to open the gui for the given gui id // open on the server side only (not sure why you shouldn't open client side too... vanilla doesn't, so we better not either) if (worldIn.isRemote) return true; playerIn.openGui(ShelvesMod.instance, GuiHandlerShelf.getGuiID(), worldIn, pos.getX(), pos.getY(), pos.getZ()); System.out.println("Called method: BlockShelf.onBlockActivated"); return true; } @Override public TileEntity createNewTileEntity(World worldIn, int meta) { return new ShelfTitleEntity(); } private boolean isBlocked(World worldIn, BlockPos pos) { return this.isBelowSolidBlock(worldIn, pos) || this.isOcelotSittingOnChest(worldIn, pos); } private boolean isBelowSolidBlock(World worldIn, BlockPos pos) { return worldIn.getBlockState(pos.up()).getBlock().isNormalCube(); } private boolean isOcelotSittingOnChest(World worldIn, BlockPos pos) { Iterator iterator = worldIn.getEntitiesWithinAABB(EntityOcelot.class, new AxisAlignedBB((double)pos.getX(), (double)(pos.getY() + 1), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 2), (double)(pos.getZ() + 1))).iterator(); EntityOcelot entityocelot; do { if (!iterator.hasNext()) { return false; } Entity entity = (Entity)iterator.next(); entityocelot = (EntityOcelot)entity; } while (!entityocelot.isSitting()); return true; } public boolean hasComparatorInputOverride() { return true; } @Override public IBlockState getStateFromMeta(int meta) { EnumFacing enumfacing = EnumFacing.getFront(meta); if (enumfacing.getAxis() == EnumFacing.Axis.Y) { enumfacing = EnumFacing.NORTH; } return this.getDefaultState().withProperty(FACING, enumfacing); } @Override public int getMetaFromState(IBlockState state) { EnumFacing facing = (EnumFacing)state.getValue(FACING); int facingbits = facing.getHorizontalIndex(); return facingbits;// | colourbits; } // necessary to define which properties your blocks use // will also affect the variants listed in the blockstates model file @Override protected BlockState createBlockState() { return new BlockState(this, new IProperty[] {FACING,SECTION}); } @Override public Item getItemDropped(IBlockState state, Random rand, int fortune) { return Item.getItemFromBlock(this); } public static enum EnumShape implements IStringSerializable { TOP("top"), MIDDLE("middle"), BOTTOM("bottom"); private final String name; private static final String __OBFID = "CL_00003061"; private EnumShape(String name) { this.name = name; } public String toString() { return this.name; } public String getName() { return this.name; } } public TileEntity createTileEntity(World world, int metadata) { return new ShelfTitleEntity(); } @Override public int getRenderType() { return 3; } } package com.rosecotton.shelvesmod; 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; /** * User: brandon3055 * Date: 06/01/2015 * * The container is used to link the client side gui to the server side inventory and it is where * you add the slots to your gui. It can also be used to sync server side data with the client but * that will be covered in a later tutorial */ public class ContainerShelf extends Container { // Stores a reference to the tile entity instance for later use private ShelfTitleEntity ShelfTitleEntity; // must assign a slot number to each of the slots used by the GUI. // For this container, we can see both the tile inventory's slots as well as the player inventory slots and the hotbar. // Each time we add a Slot to the container, it automatically increases the slotIndex, which means // 0 - 8 = hotbar slots (which will map to the InventoryPlayer slot numbers 0 - // 9 - 35 = player inventory slots (which map to the InventoryPlayer slot numbers 9 - 35) // 36 - 39 = TileInventory slots, which map to our TileEntity slot numbers 0 - 3) private final int HOTBAR_SLOT_COUNT = 9; private final int PLAYER_INVENTORY_ROW_COUNT = 3; private final int PLAYER_INVENTORY_COLUMN_COUNT = 9; private final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT; private final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT; private final int VANILLA_FIRST_SLOT_INDEX = 0; private final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT; private final int TE_INVENTORY_SLOT_COUNT = 4; public ContainerShelf(InventoryPlayer invPlayer, ShelfTitleEntity ShelfTitleEntity) { this.ShelfTitleEntity = ShelfTitleEntity; final int SLOT_X_SPACING = 18; final int SLOT_Y_SPACING = 18; final int HOTBAR_XPOS = 8; final int HOTBAR_YPOS = 109; // Add the players hotbar to the gui - the [xpos, ypos] location of each item for (int x = 0; x < HOTBAR_SLOT_COUNT; x++) { int slotNumber = x; addSlotToContainer(new Slot(invPlayer, slotNumber, HOTBAR_XPOS + SLOT_X_SPACING * x, HOTBAR_YPOS)); } final int PLAYER_INVENTORY_XPOS = 8; final int PLAYER_INVENTORY_YPOS = 51; // Add the rest of the players inventory to the gui for (int y = 0; y < PLAYER_INVENTORY_ROW_COUNT; y++) { for (int x = 0; x < PLAYER_INVENTORY_COLUMN_COUNT; x++) { int slotNumber = HOTBAR_SLOT_COUNT + y * PLAYER_INVENTORY_COLUMN_COUNT + x; int xpos = PLAYER_INVENTORY_XPOS + x * SLOT_X_SPACING; int ypos = PLAYER_INVENTORY_YPOS + y * SLOT_Y_SPACING; addSlotToContainer(new Slot(invPlayer, slotNumber, xpos, ypos)); } } if (TE_INVENTORY_SLOT_COUNT != ShelfTitleEntity.getSizeInventory()) { System.err.println("Mismatched slot count in ContainerShelf(" + TE_INVENTORY_SLOT_COUNT + ") and TileInventory (" + ShelfTitleEntity.getSizeInventory()+")"); } final int TILE_INVENTORY_XPOS = 8; final int TILE_INVENTORY_YPOS = 20; // Add the tile inventory container to the gui for (int x = 0; x < TE_INVENTORY_SLOT_COUNT; x++) { int slotNumber = x; addSlotToContainer(new Slot(ShelfTitleEntity, slotNumber, TILE_INVENTORY_XPOS + SLOT_X_SPACING * x, TILE_INVENTORY_YPOS)); } } // Vanilla calls this method every tick to make sure the player is still able to access the inventory, and if not closes the gui @Override public boolean canInteractWith(EntityPlayer player) { return ShelfTitleEntity.isUseableByPlayer(player); } // This is where you specify what happens when a player shift clicks a slot in the gui // (when you shift click a slot in the TileEntity Inventory, it moves it to the first available position in the hotbar and/or // player inventory. When you you shift-click a hotbar or player inventory item, it moves it to the first available // position in the TileEntity inventory) // At the very least you must override this and return null or the game will crash when the player shift clicks a slot // returns null if the source slot is empty, or if none of the the source slot items could be moved // otherwise, returns a copy of the source stack @Override public ItemStack transferStackInSlot(EntityPlayer player, int sourceSlotIndex) { Slot sourceSlot = (Slot)inventorySlots.get(sourceSlotIndex); if (sourceSlot == null || !sourceSlot.getHasStack()) return null; ItemStack sourceStack = sourceSlot.getStack(); ItemStack copyOfSourceStack = sourceStack.copy(); // Check if the slot clicked is one of the vanilla container slots if (sourceSlotIndex >= VANILLA_FIRST_SLOT_INDEX && sourceSlotIndex < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) { // This is a vanilla container slot so merge the stack into the tile inventory if (!mergeItemStack(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT, false)){ return null; } } else if (sourceSlotIndex >= TE_INVENTORY_FIRST_SLOT_INDEX && sourceSlotIndex < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) { // This is a TE slot so merge the stack into the players inventory if (!mergeItemStack(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) { return null; } } else { System.err.print("Invalid slotIndex:" + sourceSlotIndex); return null; } // If stack size == 0 (the entire stack was moved) set slot contents to null if (sourceStack.stackSize == 0) { sourceSlot.putStack(null); } else { sourceSlot.onSlotChanged(); } sourceSlot.onPickupFromSlot(player, sourceStack); return copyOfSourceStack; } // pass the close container message to the tileEntityInventory (not strictly needed for this example) // see ContainerChest and TileEntityChest @Override public void onContainerClosed(EntityPlayer playerIn) { super.onContainerClosed(playerIn); this.ShelfTitleEntity.closeInventory(playerIn); } } package com.rosecotton.shelvesmod; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.entity.RenderItem; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.SidedProxy; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.common.registry.LanguageRegistry; import net.minecraftforge.fml.relauncher.Side; import com.rosecotton.shelvesmod.BlockShelf; //import com.becky.testmod01.Testmod01; @Mod(modid = ShelvesMod.MODID, name = ShelvesMod.MODNAME, version = ShelvesMod.VERSION) public class ShelvesMod { public static Block shelfBlock; //public static Item brickIngot; public static final String MODID = "shelvesmod"; public static final String MODNAME = "RoseCotton's Shelves Mod for 1.8"; public static final String VERSION = "1.0"; public static int type; @Instance(value = "shelvesmod") public static ShelvesMod instance = new ShelvesMod(); public static class MySidedProxyHolder { @SidedProxy(modId="shelvesmod",clientSide="com.rosecotton.shelvesmod.ClientProxy", serverSide="com.rosecotton.shelvesmod.CommonProxy") public static CommonProxy proxy; } public class CommonProxy { // Common or server stuff here that needs to be overridden on the client } public class ClientProxy extends CommonProxy { // Override common stuff with client specific stuff here } @EventHandler public void preInit(FMLPreInitializationEvent event) { //blocks shelfBlock = new BlockShelf(type); LanguageRegistry.addName(shelfBlock, "Shelf Block"); GameRegistry.registerTileEntity(ShelfTitleEntity.class, "shelfTitleEntity"); //was com.rosecotton.shelvesmod.ShelfTitleEntity.class //items //brickIngot = new ItemBrickIngot(); //MOVE GAMEREGISTRY TO ITEM CLASS? //GameRegistry.registerItem(brickIngot, ((ItemBrickIngot) brickIngot).getName()); //LanguageRegistry.addName(brickIngot, "Brick Ingot"); NetworkRegistry.INSTANCE.registerGuiHandler(ShelvesMod.instance, GuiHandlerRegistry.getInstance()); GuiHandlerRegistry.getInstance().registerGuiHandler(new GuiHandlerShelf(), GuiHandlerShelf.getGuiID()); } @EventHandler public void init(FMLInitializationEvent event) { //System.out.println("Called method: init"); if(event.getSide() == Side.CLIENT) { RenderItem renderItem = Minecraft.getMinecraft().getRenderItem(); renderItem.getItemModelMesher().register(Item.getItemFromBlock(shelfBlock), 0, new ModelResourceLocation(ShelvesMod.MODID + ":" + ((BlockShelf) shelfBlock).getName(), "shelfBlock")); Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(shelfBlock),0, new ModelResourceLocation(ShelvesMod.MODID+":"+ "shelfBlock", "inventory")); } //recipes GameRegistry.addRecipe(new ItemStack(shelfBlock), new Object[]{ " ", " A", " AA", 'A', Items.stick //getItemFromBlock(Blocks.planks) }); } @EventHandler public void postInit(FMLPostInitializationEvent event) { System.out.println("Called method: postInit"); } } And there are a couple GUI java files to go with that, as well as my shelf block model files. hw developer in a sw world
March 8, 201510 yr http://www.minecraftforge.net/forum/index.php/topic,28348.msg146006.html#msg146006
March 9, 201510 yr Hi Have you looked in the RenderItemFrame.doRender()? The item rendering is called from here. -TGG
March 9, 201510 yr Author Ah! no, I hadn't found that one. I had only found EntityItemFrame, but this RenderItemFrame class is what I was looking for. I'll go study it and find out if I can use some of it for what I want. Thanks! hw developer in a sw world
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.