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