Posted April 8, 201510 yr Hey Forge-Community, first of all i want to excusme me for my bad english, but i will try it The thread will be divided into three parts, first my problem, second my solution and at least my research why the problem exists!? If it is not possible to read, please write it.. and i retry it! Problem I want to create one block with 18 different subtypes. This should be a ore, an ore with always the same texture but different ore colors (coloring by code), and also diffent hardness values, harvestLevels and dropRates. The problem is the meta... i have in game 18 different items with diffent colors.. yay! But if i place one of these items i place always the same block with it. Always the block with meta = 0! Solution (I write my full code..!) 1) Create a base class for all my blocks which inherits from Block (I need it for easier .json registration!) public class BlockBase extends Block{ public BlockBase(Material material){ super(material); } } 2) Create a base class for all my meta-based blocks which inherits from BlockBase. This class has a abstract method to get the item color for the ItemBlock! (I know, i can do it by the same way as for the block, but i will need it for later use!!). The enum "JSON" is for my different registration types.. i can say:"Only one json for the block (by name)" or "For each meta in the block, ignore base-name, one json" or "one json for each name + subtype"! This shouldnt be relevant for this thread, but if anyone asks.. this is why i do this! The methods "getSubTypes()", "getJSON()", "getBasicName()" and "getMetaName()" are also relevant for my own json registering and the ItemBlock class! At last this blockClass overwrites the methods "damageDropped(IBlockState state)" and "getSubBlocks(Item item, CreativeTabs tab, List list)" like in 1.7! public abstract class BlockBaseMeta extends BlockBase{ @SideOnly(Side.CLIENT) public abstract int getColorFromItemStack(ItemStack itemStack, int layer); public enum JSON{ /** Requires for each basic name plus subType a json file. * The file is located at items/[basicname + subType].json*/ BASICNAME_AND_SUBTYPE, /** Requires only for each basicname a json file. * The file is located at items/[basicname].json */ BASICNAME, /** Requires for each subType a json file, basic name will be ignored. * The file is located at items/[subType].json */ SUBTYPE; } private JSON json; private String[] subTypes; private String basicName; public BlockBaseMeta(Material material, String basicName, String[] subTypes, JSON json){ super(material); this.setUnlocalizedName(this.basicName = basicName); this.subTypes = subTypes; this.json = json; } public String[] getSubTypes(){ return this.subTypes; } public JSON getJSON(){ return this.json; } public String getBasicName(){ return this.basicName; } public String getMetaName(int meta){ return this.subTypes[meta]; } @Override public int damageDropped(IBlockState state) { return this.getMetaFromState(state); } @Override public Item getItemDropped(IBlockState state, Random random, int fortune){ return new ItemStack(this).getItem(); } @Override public void getSubBlocks(Item item, CreativeTabs tab, List list) { for(int i = 0; i < this.subTypes.length; i++) { list.add(new ItemStack(item, 1, i)); } } } 3) Create a class which inherits from ItemBlock, for the different items for the meta-block! (Here you can the calls to the methods to the class before!) public class BlockBaseMetaItem extends ItemBlock { private final BlockBaseMeta blockBaseMeta; public BlockBaseMetaItem(Block blockBaseMeta){ super(blockBaseMeta); this.setHasSubtypes(true); this.blockBaseMeta = (BlockBaseMeta)blockBaseMeta; if (this.blockBaseMeta.getJSON() == BlockBaseMeta.JSON.SUBTYPE){ for(String subType : this.blockBaseMeta.getSubTypes()){ ModelBakery.addVariantName(this, subType); } } if (this.blockBaseMeta.getJSON() == BlockBaseMeta.JSON.BASICNAME_AND_SUBTYPE){ for(String subType : this.blockBaseMeta.getSubTypes()){ ModelBakery.addVariantName(this, this.blockBaseMeta.getBasicName() + subType); } } } @Override public String getUnlocalizedName(ItemStack itemStack){ return this.blockBaseMeta.getUnlocalizedName() + this.blockBaseMeta.getSubTypes()[MathHelper.clamp_int(itemStack.getItemDamage(), 0, this.blockBaseMeta.getSubTypes().length - 1)]; } @Override public void getSubItems(Item item, CreativeTabs creativeTabs, List list){ for (int i = 0; i < this.blockBaseMeta.getSubTypes().length; i++){ list.add(new ItemStack(this, 1, i)); } } @Override public int getMetadata(int meta){ return meta; } @SideOnly(Side.CLIENT) @Override public int getColorFromItemStack(ItemStack itemStack, int layer){ return this.blockBaseMeta.getColorFromItemStack(itemStack, layer); } public String getBasicName(){ return this.blockBaseMeta.getBasicName(); } public String getSimpleName(int meta){ return this.blockBaseMeta.getMetaName(meta); } } 4) Create a base block class for my "Minerals" (I need the same for a later use!) This class sets overwrites now the methods "getColorFromItemStack(ItemStack itemStack, int renderPass)", "quantityDropped(IBlockState state, int fortune, Random random)", "getHarvestLevel(IBlockState state)", "getBlockHardness(World world, BlockPos pos)", "colorMultiplier(IBlockAccess blockAccess, BlockPos pos, int renderPass)" to set the block exact to this meta i want! To do this i write another class, which saves my meta values for this.. see it at point 5! public class BlockMineral extends BlockBaseMeta { private BlockMineralMetaData[] blockMetaDatas; public BlockMineral(String name, BlockMineralMetaData[] blockMetaDatas){ super(Material.rock, name, BlockMineralMetaData.getNameArray(blockMetaDatas), JSON.BASICNAME); this.blockMetaDatas = blockMetaDatas; this.setCreativeTab(ZCreativeTabs.blocks); this.setHardness(10); this.setResistance(10); this.setHarvestLevel("pickaxe", 10); this.setStepSound(Block.soundTypeStone); ZRegistry.registerBlock(this, BlockBaseMetaItem.class); } @Override public int getColorFromItemStack(ItemStack itemStack, int renderPass) { int meta = itemStack.getItemDamage(); if (meta > this.blockMetaDatas.length){ return 16777215; } return blockMetaDatas[meta].getColor(renderPass); } @Override public int quantityDropped(IBlockState state, int fortune, Random random) { int meta = this.getMetaFromState(state); if (blockMetaDatas[meta].quantityDropMin == blockMetaDatas[meta].quantityDropMax) return blockMetaDatas[meta].quantityDropMin; int quantity = blockMetaDatas[meta].quantityDropMin + (fortune == 0 ? 0 : random.nextInt(fortune)); return quantity > this.blockMetaDatas[meta].quantityDropMax ? this.blockMetaDatas[meta].quantityDropMin : quantity; } @Override public int getHarvestLevel(IBlockState state) { return this.blockMetaDatas[this.getMetaFromState(state)].harvestLevel; } @Override public float getBlockHardness(World world, BlockPos pos) { return this.blockMetaDatas[this.getMetaFromState(world.getBlockState(pos))].hardness; } @SideOnly(Side.CLIENT) @Override public int colorMultiplier(IBlockAccess blockAccess, BlockPos pos, int renderPass) { return this.getColor(this.getMetaFromState(blockAccess.getBlockState(pos)), renderPass); } private int getColor(int meta, int renderPass){ if (meta > this.blockMetaDatas.length){ return 16777215; } return blockMetaDatas[meta].getColor(renderPass); } } 5) This class only saves the different values for one meta value public class BlockMineralMetaData extends BlockMetaData{ public final float hardness; public final int harvestLevel; public final int quantityDropMin; public final int quantityDropMax; public BlockMineralMetaData(String name, float hardness, int harvestLevel, int quantityDropMin, int quantityDropMax, int...colors){ super(name, colors); this.hardness = hardness; this.harvestLevel = harvestLevel; this.quantityDropMin = quantityDropMin; this.quantityDropMax = quantityDropMax; } } 6) At last i only need to create an Block class for my ores.. i also can now create a class for MineralBlocks (Like IronBlock, GoldBlock e.g.). This class inherits from my BlockMineral.class! (You see there are currently one 6 different colors... this are only test-colors.. i dont wanna create a pink vanadium ore! ) public class BlockMineralOre extends BlockMineral{ /** * This enumeration exists only to get the meta id (== ordinal) * and to get a better overview over the code, in recipes e.g. */ public enum Meta{ MANGANESE(new BlockMineralMetaData("Manganese", 5, 2, 1, 4, Color.BLUE.getRGB())), NICKEL(new BlockMineralMetaData("Nickel", 5, 2, 1, 4, Color.DARK_GRAY.getRGB())), COBALT(new BlockMineralMetaData("Cobalt", 5, 2, 1, 4, Color.GRAY.getRGB())), TUNGSTEN(new BlockMineralMetaData("Tungsten", 5, 2, 1, 4, Color.CYAN.getRGB())), MOLYBDENUM(new BlockMineralMetaData("Molybdenum", 5, 2, 1, 4, Color.GREEN.getRGB())), VANADIUM(new BlockMineralMetaData("Vanadium", 5, 2, 1, 4, Color.pink.getRGB())), COPPER(new BlockMineralMetaData("Copper", 5, 2, 1, 4)), SILVER(new BlockMineralMetaData("Silver", 5, 2, 1, 4)), LEAD(new BlockMineralMetaData("Lead", 5, 2, 1, 4)), TIN(new BlockMineralMetaData("Tin", 5, 2, 1, 4)), ZINC(new BlockMineralMetaData("Zinc", 5, 2, 1, 4)), ALUMINUM(new BlockMineralMetaData("Aluminum", 5, 2, 1, 4)), MAGNESIUM(new BlockMineralMetaData("Magnesium", 5, 2, 1, 4)), BERYLLIUM(new BlockMineralMetaData("Beryllium", 5, 2, 1, 4)), LITHIUM(new BlockMineralMetaData("Lithium", 5, 2, 1, 4)), MITHRIL(new BlockMineralMetaData("Mithril", 5, 2, 1, 4)); private final BlockMineralMetaData blockMineralMetaData; Meta(BlockMineralMetaData blockMineralMetaData) { this.blockMineralMetaData = blockMineralMetaData; } public static BlockMineralMetaData[] getMetaDataArray() { ArrayList<BlockMineralMetaData> result = new ArrayList(Meta.values().length); for(Meta meta : Meta.values()){ result.add(meta.blockMineralMetaData); } result.trimToSize(); return result.toArray(new BlockMineralMetaData[result.size()]); } } public BlockMineralOre(){ super("blockOre", Meta.getMetaDataArray()); } } Why exists my problem? Now.. firstly i debugged through the methods and .. what is this.. my meta in the block is always 0. Here are some suggestions from my side!!! 1. I inherits in my BlockBaseMetaItem.class from ItemBlock .. and not from ItemBlockWithMetaData (like 1.7.. becauce it doesnt exists!) 2. In the "onItemUse" method in the ItemBlock.class isnt set the meta id to the block which is placed! 3. The "damageDropped(IBlockState state)" method in Block class, which i have overwritten in my BlockBaseMeta.class give me only a IBlockState... and how i can return the meta.. i found the method "getMetaFromState(IBlockState state)" in the Block class.. but the content of this method is .. i dont know.. it checks only if if the state is null and not empty, return an error - otherwise always 0... but this is not right or? Now.. i will finish this thread.. and if you think.. omg learn english or omg youre are fcking n00b... then say it! Thanks for your help. Greeting Zootaxz
April 8, 201510 yr Problem I want to create one block with 18 different subtypes. Metadata didn't suddenly allow for more than 16 because 1.8 happened. It's still 16, but that other types of states can exist as well, such as ones being inferred based on neighboring blocks or TileEntity data. getMetaFromBlockState can not return a value greater than 15. Ever. 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.
April 8, 201510 yr Zootaxz, I don't think you understand some of the important things about metadata. Here are some things to consider: 1) in 1.8, metadata is now sort of hidden from the code and instead you should use a Property for the block, which can vary in each block's IBlockState. There is still metadata though, so you need to have methods in your block to convert from state to metadata and from metadata to state. 2) The built-in metadata is only 4-bits per block position, so you can only have 16 variations in one block. 3) The JSONs map the property values to the models, and the models map to the textures. If you implement the above three points, then Minecraft will properly save the metadata and also sync it between client and server for you. It seems that you're trying to create some entirely new metadata system? How are you syncing between client and server? How is it getting saved and loaded? I think the problem is that you can certainly create all sorts of classes and fields to hold extended data, but you also have to consider the syncing and saving processes. Check out my tutorials here: http://jabelarminecraft.blogspot.com/
April 9, 201510 yr Author Thanks for your answers... i will try it and response again in some days (no really much time at the moment )
April 9, 201510 yr Author Okay.. i found some minutes to implement the Property into my blocks... and yes! it works! Thanks again you two [Can be closed]
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.