RoseCotton Posted March 2, 2015 Posted March 2, 2015 Hi, All. I'm studying up on the stairs block model because I want to edit it into two-tier shelves on which items can be stored and displayed. Does anyone know how to add an item into a block so that it is rendered in a specific position? Quote hw developer in a sw world
Draco18s Posted March 2, 2015 Posted March 2, 2015 You will need a tile entity for your block that has an inventory. Then you'd render each inventory element in the appropriate place based off its index. Quote Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
RoseCotton Posted March 2, 2015 Author Posted March 2, 2015 On 3/2/2015 at 10:13 PM, Draco18s said: You will need a tile entity for your block that has an inventory. Then you'd render each inventory element in the appropriate place based off its index. Thank you, Draco18s. Can anyone point me toward an example of a title entity? The chest and the item frame are the closest I can guess, but the code is obfuscated and really, really difficult for a beginner modder to read. Do you know if there are any good tutorials? Or examples someone has been kind enough to share (and hopefully comment...)? Quote hw developer in a sw world
Draco18s Posted March 2, 2015 Posted March 2, 2015 http://www.minecraftforge.net/wiki/Basic_Tile_Entity Quote Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
RoseCotton Posted March 2, 2015 Author Posted March 2, 2015 Thanks! I'd ignored that tutorial because I thought it was only applicable to pre-1.8 due to the x,y,z format of the position data. I'll check it out. Quote hw developer in a sw world
Draco18s Posted March 2, 2015 Posted March 2, 2015 Its not completely irrelevant. Quote Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
TheGreyGhost Posted March 3, 2015 Posted March 3, 2015 Hi This example project has working examples of a TileEntity, a container, and a TileEntitySpecialRenderer, all of which might be useful in this case. https://github.com/TheGreyGhost/MinecraftByExample This tutorial site has a couple of entries on TileEntities and containers too, for background info. http://greyminecraftcoder.blogspot.com.au/p/list-of-topics.html -TGG Quote
Draco18s Posted March 3, 2015 Posted March 3, 2015 Also, here's how I rendered a container item. https://github.com/Draco18s/Artifacts/blob/master/main/java/com/draco18s/artifacts/client/ModelPedestal.java#L60-80 It only does one item (intended to be rotated flat against a top surface) but it should give you an idea of the necessary parts. Quote Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
RoseCotton Posted March 5, 2015 Author Posted March 5, 2015 On 3/3/2015 at 12:18 PM, TheGreyGhost said: This example project has working examples of a TileEntity, a container, and a TileEntitySpecialRenderer, all of which might be useful in this case. https://github.com/TheGreyGhost/MinecraftByExample This tutorial site has a couple of entries on TileEntities and containers too, for background info. http://greyminecraftcoder.blogspot.com.au/p/list-of-topics.html -TGG Thank you very much, Grey Ghost, for minecraftbyexample! finally, some comments! I was looking through the mbe30_inventory_basic java file to see what I can adopt for my ShelfBlock title entity and following some event handler tutorials and put together the files ShelfTitleEntity.java and ShelvesEventHandler.java, only to find that now when I place my shelves block (whose item looks like my shelves) it comes out as a chest! I thought I had understood each code addition enough (due to the well-named methods and much-appreciated comments) that I would have noticed if I suddenly switched the block model to the one for a chest. What key words can I look for to indicate where in the files I might have switched the model from shelfBlock to chest? ShelvesMod.java 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.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) { //System.out.println("Called method: preInit"); //blocks shelfBlock = new BlockShelf(type); LanguageRegistry.addName(shelfBlock, "Shelf Block"); GameRegistry.registerTileEntity(com.rosecotton.shelvesmod.ShelfTitleEntity.class, "shelfTitleEntity"); //items //brickIngot = new ItemBrickIngot(); //MOVE GAMEREGISTRY TO ITEM CLASS? //GameRegistry.registerItem(brickIngot, ((ItemBrickIngot) brickIngot).getName()); //LanguageRegistry.addName(brickIngot, "Brick Ingot"); } @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(brickIngot, 0, new ModelResourceLocation(Testmod01.MODID + ":" + ((ItemBrickIngot)brickIngot).getName(), "brickIngot")); //Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(brickIngot,0, new ModelResourceLocation(Testmod01.MODID + ":" + ((ItemBrickIngot)brickIngot).getName(), "inventory")); 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) }); //GameRegistry.addShapelessRecipe(new ItemStack(brickIngot, 4), new Object[] //{ // brickBlock//new ItemStack(brickBlock, 1, 1) //}); //I left off the third parameter in ItemStack because it means damage //GameRegistry.addSmelting(new ItemStack(brickBlock, 1), new ItemStack(brickIngot, 1), 0.1F); } } BlockShelf.java 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); } //@Override // public int getRenderType() //{ // return -1; //} 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); } public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumFacing side, float hitX, float hitY, float hitZ) { // if (worldIn.isRemote) // { return true; // } } public TileEntity createNewTileEntity(World worldIn, int meta) { return new TileEntityChest(); } 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(); } } ShelfTitleEntity.java package com.rosecotton.shelvesmod; import java.util.Arrays; 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; private ItemStack[] itemStacks = new ItemStack[NUMBER_OF_SLOTS]; //public String fieldOne; //public String fieldTwo; //public String fieldThree; //public String fieldFour; // will add a key for this container to the lang file so we can name it in the GUI @Override public String getName() { return "shelfContainer"; } @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) { } //----------------------------------------------------------------------------------------------------------- //The following method is not needed for this example but are part of IInventory so must be implemented @Override public void closeInventory(EntityPlayer player) { } // 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); } } } @Override public int getField(int id) { // TODO Auto-generated method stub return 0; } @Override public void setField(int id, int value) { // TODO Auto-generated method stub } @Override public int getFieldCount() { // TODO Auto-generated method stub return 0; } // set all slots to empty @Override public void clear() { Arrays.fill(itemStacks, null); } } ShelvesEventHandler.java package com.rosecotton.shelvesmod; import com.rosecotton.shelvesmod.ShelvesMod; public class ShelvesEventHandler { } Quote hw developer in a sw world
RoseCotton Posted March 5, 2015 Author Posted March 5, 2015 Ok, this is hilarious; the sun finally came up in my test game and now I see that when I place my BlockShelf, it actually renders a chest embedded in my shelves. I found that the I'd changed the BlockShelf class to extend BlockContainer, not just Block, and that BlockContainer has a getRenderType() method that returns -1 instead of 3 like Block's getRenderType() method. So I overrode getRenderType() in BlockShelf to return 3, but that didn't seem to help. Quote hw developer in a sw world
Draco18s Posted March 5, 2015 Posted March 5, 2015 Show your client proxy. Quote Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
RoseCotton Posted March 5, 2015 Author Posted March 5, 2015 Here's the ShelvesMod.java file that has the client proxy stuff: 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.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(com.rosecotton.shelvesmod.ShelfTitleEntity.class, "shelfTitleEntity"); //items //brickIngot = new ItemBrickIngot(); //MOVE GAMEREGISTRY TO ITEM CLASS? //GameRegistry.registerItem(brickIngot, ((ItemBrickIngot) brickIngot).getName()); //LanguageRegistry.addName(brickIngot, "Brick Ingot"); } @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) }); } } Here's BlockShelf.java Reveal hidden contents 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); } public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumFacing side, float hitX, float hitY, float hitZ) { // if (worldIn.isRemote) // { return true; // } } public TileEntity createNewTileEntity(World worldIn, int meta) { return new TileEntityChest(); } 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; } } Here's ShelfTitleEntity.java Reveal hidden contents package com.rosecotton.shelvesmod; import java.util.Arrays; 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; 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) { } //----------------------------------------------------------------------------------------------------------- //The following method is not needed for this example but are part of IInventory so must be implemented @Override public void closeInventory(EntityPlayer player) { } // 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 != null) { NBTTagCompound dataForThisSlot = new NBTTagCompound(); dataForThisSlot.setByte("Slot", (byte) i); this.itemStacks.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); } } } @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); } } Here's ShelvesEventHandler.java (haven't done anything with this yet, one thing at a time...) Reveal hidden contents package com.rosecotton.shelvesmod; import com.rosecotton.shelvesmod.ShelvesMod; public class ShelvesEventHandler { } My json model files haven't changed and are posted above. Quote hw developer in a sw world
RoseCotton Posted March 5, 2015 Author Posted March 5, 2015 UPDATE: I fixed it. I had: public TileEntity createNewTileEntity(World worldIn, int meta) { return new TitleEntityChest(); } instead of: public TileEntity createNewTileEntity(World worldIn, int meta) { return new ShelfTitleEntity(); } Quote hw developer in a sw world
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.