Jump to content

Recommended Posts

Posted

UPDATE 5-8-2016: I have now figured out how to get my slabs working, and I have updated this post with the working code. The original post can be seen in the spoiler at the bottom. Thanks for the help, everyone! If you have any questions about certain parts of my code or suggestions on how to do it better let me know!

 

Working Code for slabs with additional blockstates/metadata in Minecraft 1.8.9:

 

 

My code package structure (for reference):

colore

-client

--render

-common

--blocks

--creativeTabs

--init

--items

--worldGeneration

-proxy

-utility

 

//common.blocks package//

 

BlockColoreSlab.java

package com.supergeniuszeb.colore.common.blocks;

import java.util.Random;

import net.minecraft.block.BlockSlab;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.World;

//An abstract class for both half-slabs and full/double slabs.
public abstract class BlockColoreSlab extends BlockSlab implements IMetaBlockName{

public BlockColoreSlab(String unlocalizedName) {
	super(Material.rock);
	this.setHardness(1.5f);
	this.setHarvestLevel("pickaxe", 0);
	this.setResistance(10.0f);
	this.setUnlocalizedName(unlocalizedName);
	this.useNeighborBrightness = !this.isDouble();

	//Sets default state depending on whether block is a half-slab or double-slab.
	IBlockState blockState = this.blockState.getBaseState();
        blockState = blockState.withProperty(SHADE, EnumShade.NORMAL);
        if (!this.isDouble()) {
            blockState = blockState.withProperty(HALF, EnumBlockHalf.BOTTOM);
        }

        this.setDefaultState(blockState);
}

public enum EnumShade implements IStringSerializable {
	NORMAL(0, "normal"),
	LIGHT(1, "light"),
	LIGHTER(2, "lighter"),
	DARK(3, "dark"),
	DARKER(4, "darker");

	private int ID;
	private String name;

	private EnumShade(int ID, String name) {
		this.ID = ID;
		this.name = name;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		return getName();
	}

	public int getID() {
        return ID;
    }

}

//The shade ("light", "dark", etc.) of the slab. The "HALF" property is defined in the vanilla BlockSlab class so I don't need to make my own.
public static final PropertyEnum SHADE = PropertyEnum.create("shade", BlockColoreSlab.EnumShade.class);

//Function to get the variant property created above based on the item.
@Override
public final Object getVariant(final ItemStack itemstack) {
	return getStateFromMeta(itemstack.getMetadata()).getValue(SHADE);
}

//Function to get the variant property.
@Override
public final IProperty getVariantProperty() {
	return SHADE;
}

//I feel like there must be a simpler way to do this, but here's how I make the
//double slabs drop their corresponding half slabs. Note my use of the getHalfSlab()
//method I created for indirectly obtaining the value of ItemSlab's singleSlab
//param, which is private.
@Override
public Item getItemDropped(IBlockState state, Random rand, int fortune){
	int meta = this.getMetaFromState(state);
	Item item = Item.getItemFromBlock(((ItemBlockColoreSlab) Item.getItemFromBlock(this)).getHalfSlab());
	switch (meta) {
		case 0:
		case 5:
			return new ItemStack(item, 2, 0).getItem();
		case 1:
		case 6:
			return new ItemStack(item, 2, 1).getItem();
		case 2:
		case 7:
			return new ItemStack(item, 2, 2).getItem();
		case 3:
		case 8:
			return new ItemStack(item, 2, 3).getItem();
		case 4:
		case 9:
			return new ItemStack(item, 2, 4).getItem();
		default:
			return new ItemStack(item, 2, 0).getItem();
	}
}

@Override
protected BlockState createBlockState() {
	return new BlockState(this, new IProperty[] {SHADE, HALF});
}

//Converts an IBlockState into metadata.
@Override
public IBlockState getStateFromMeta(int meta) {

	//A blockState is created, which is assigned the SHADE property depending on its metadata, as well as the HALF property, if it is a half-slab.
	IBlockState blockState = this.getDefaultState();

	if (!this.isDouble()) { //If the block is a BlockColoreHalfSlab
		switch (meta) {
			case 0:
				blockState = blockState.withProperty(SHADE, EnumShade.NORMAL).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break; //Note-to-self: DON'T FORGET TO USE THIS IN SWITCH STATEMENTS IF RETURN STATEMENTS AREN'T INVOLVED!
			case 1:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHT).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break;
			case 2:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHTER).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break;
			case 3:
				blockState = blockState.withProperty(SHADE, EnumShade.DARK).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break;
			case 4:
				blockState = blockState.withProperty(SHADE, EnumShade.DARKER).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break;
			case 5:
				blockState = blockState.withProperty(SHADE, EnumShade.NORMAL).withProperty(HALF, EnumBlockHalf.TOP);
				break;
			case 6:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHT).withProperty(HALF, EnumBlockHalf.TOP);
				break;
			case 7:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHTER).withProperty(HALF, EnumBlockHalf.TOP);
				break;
			case 8:
				blockState = blockState.withProperty(SHADE, EnumShade.DARK).withProperty(HALF, EnumBlockHalf.TOP);
				break;
			case 9:
				blockState = blockState.withProperty(SHADE, EnumShade.DARKER).withProperty(HALF, EnumBlockHalf.TOP);
				break;
			default:
				blockState = blockState.withProperty(SHADE, EnumShade.NORMAL).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break;
		}
	} else { //If the block is a BlockColoreDoubleSlab
		switch (meta) {
			case 0:
				blockState = blockState.withProperty(SHADE, EnumShade.NORMAL);
				break;
			case 1:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHT);
				break;
			case 2:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHTER);
				break;
			case 3:
				blockState = blockState.withProperty(SHADE, EnumShade.DARK);
				break;
			case 4:
				blockState = blockState.withProperty(SHADE, EnumShade.DARKER);
				break;
			default:
				blockState = blockState.withProperty(SHADE, EnumShade.NORMAL);
				break;
		}
	}

	return blockState;
}

//Converts metadata into an IBlockState.
@Override
public int getMetaFromState(IBlockState state) {

    EnumShade shade = (EnumShade) state.getValue(SHADE);
    
    if (!this.isDouble()) {
    	EnumBlockHalf half = (EnumBlockHalf) state.getValue(HALF);
    	
    	//0-4 are bottom slabs, and 5-9 are the top slabs, so if the HALF property = top,
    	//then 5 is added to the ID integer assigned to the SHADE property. This is done
    	//to match up with how I've assigned the 10 different metadata values. (I hope
    	//this comment made sense so I don't come back later trying to find out why I did
    	//this and get disappointed with my former self's explanatory skills...)
    	if (half == EnumBlockHalf.TOP) {
    		return shade.getID() + 5; 
    	}
    }
    
    return shade.getID();
}

//This insures that  the meta block drops an item-block with the correct metadata when mined. This is
//somewhat trickier than with a regular block since you don't want to drop a "top" or "bottom" half slab.
//You only want to drop... well, just a slab! (Or more technically, a default, or bottom, half slab.
//Of course, if you're breaking a double-slab, it shouldn't drop a block with the HALF property at all.
@Override
public int damageDropped(IBlockState state) {
	if (!this.isDouble()) {
		//Using my neat math tricks in conjuction with how I've set up the 9 metadata values so that
		//0-4 are bottom slabs and 5-9 are top slabs.
		if (getMetaFromState(state) > 4) { //If the block is a top slab, then drop a bottom slab.
			return getMetaFromState(state) - 5;
		}
	}
	//If the block is a bottom slab or double slab, then drop a block with a metadata between 0-4.
	//The value of the SHADE property is assigned to the same 5 integers for both bottom half slabs
	//and double slabs, so this works. Hooray for clever metadata-blockstate-math-stuff!
    return getMetaFromState(state);
}

//Used to get the last part of the unlocalized name for the item-block.
//The structure of the unlocalized name is: tile.blockname.specialname.name
@Override
public String getSpecialName(ItemStack stack) {
	switch (stack.getItemDamage()) {
		case 0:
			return "normal";
		case 1:
			return "light";
		case 2:
			return "lighter";
		case 3:
			return "dark";
		case 4:
			return "darker";
		default:
			return "normal";
	}
}

@Override
    public final String getUnlocalizedName(final int meta) {
        return this.getUnlocalizedName();
    }

//This ensures that the pick-block button (normally middle-click) will give
//an item-block with the correct metadata. Top & bottom half slabs will both
//return bottom slabs, and double slabs will return themselves.
@Override
public ItemStack getPickBlock(MovingObjectPosition target, World world, BlockPos pos) {
	int meta = this.getMetaFromState(world.getBlockState(pos));
	if (meta > 4) { //If the block is a top half slab
		meta = meta - 5; //Pick-block should return a bottom half slab...
	}
    return new ItemStack(Item.getItemFromBlock(this), 1, meta);
}
}

 

BlockColoreSlabHalf.java

package com.supergeniuszeb.colore.common.blocks;

public class BlockColoreSlabHalf extends BlockColoreSlab {

public BlockColoreSlabHalf(String unlocalizedName) {
	super(unlocalizedName);
}

@Override
public boolean isDouble() {
	return false;
}

}

 

BlockColoreSlabDouble.java

package com.supergeniuszeb.colore.common.blocks;

public class BlockColoreSlabDouble extends BlockColoreSlab {

public BlockColoreSlabDouble(String unlocalizedName) {
	super(unlocalizedName);
}

@Override
public boolean isDouble() {
	return true;
}

}

 

ItemBlockColoreSlab.java

package com.supergeniuszeb.colore.common.blocks;

import java.util.ArrayList;
import java.util.List;

import net.minecraft.block.Block;
import net.minecraft.block.BlockSlab;
import net.minecraft.item.Item;
import net.minecraft.item.ItemSlab;
import net.minecraft.item.ItemStack;

/*
* Wrapper class to make sure that GameRegistry.registerBlock() calls the right constructor.
*/
public class ItemBlockColoreSlab extends ItemSlab {

public ItemBlockColoreSlab(final Block block, final BlockColoreSlabHalf singleSlab, final BlockColoreSlabDouble doubleSlab) {
	super(block, singleSlab, doubleSlab);
	this.setHasSubtypes(true);
        this.getSubBlocks(slabList, this, 5);
        this.setHalfSlab(singleSlab);
}

//This variable and the setter & getter that follow were made by me to get the value of the private
//param this.singleSlab from ItemSlab's constructor. This is my indirect and probably inefficient
//way to make my double slabs drop their half slab counterparts. See usage in BlockColoreSlab.getItemDropped().
private BlockSlab halfSlab;

public void setHalfSlab(BlockSlab slab) {
	this.halfSlab = slab;
}

public BlockSlab getHalfSlab() {
	return this.halfSlab;
}

@Override
    public String getUnlocalizedName(ItemStack stack) {
	//If the block is a double slab, "double_" will be added to the unlocalized name.
	//Note how "tile." is removed via .substring after "tile.double_" is added so that
	//"double_" can be effectively added to the unlocalizedName after the "tile."
	//It's kind of messy, but at least it works.
	if (((BlockColoreSlab) this.getBlock()).isDouble()) {
		return "tile.double_" + super.getUnlocalizedName(stack).substring(5) + "." + ((IMetaBlockName)this.block).getSpecialName(stack);
	}
        return super.getUnlocalizedName(stack) + "." + ((IMetaBlockName)this.block).getSpecialName(stack);
}

public static List slabList = new ArrayList<Item>(5) {};

	//This will add all the different metadata variations of the slabs
	//as "ItemStack"s to the slabList list. Used when adding metadata
	//blocks to the creative tabs.
	public void getSubBlocks(List slabList, Item item, int range) {
		//This prevents any double slabs from showing up in the creative tab.
		if (!((BlockColoreSlab) Block.getBlockFromItem(item)).isDouble()) {
			for (int i = 0; i < range; ++i) {
	            slabList.add(new ItemStack(item, 1, i));
	        }
		}
	}

}

 

 

//common.init package//

 

ModBlocks.java (renamed from BlockRegistry.java)

package com.supergeniuszeb.colore.common.init;

import com.supergeniuszeb.colore.common.blocks.BlockColore;
import com.supergeniuszeb.colore.common.blocks.BlockColoreOre;
import com.supergeniuszeb.colore.common.blocks.BlockColoreSlab;
import com.supergeniuszeb.colore.common.blocks.BlockColoreSlabDouble;
import com.supergeniuszeb.colore.common.blocks.BlockColoreSlabHalf;
import com.supergeniuszeb.colore.common.blocks.ItemBlockColore;
import com.supergeniuszeb.colore.common.blocks.ItemBlockColoreSlab;

import net.minecraftforge.fml.common.registry.GameRegistry;

public class ModBlocks {

//regular blocks
public static BlockColore block_of_red;
public static BlockColore block_of_reddish_orange;
public static BlockColore block_of_orange;
public static BlockColore block_of_orangish_yellow;
public static BlockColore block_of_yellow;
public static BlockColore block_of_yellowish_green;
public static BlockColore block_of_green;
public static BlockColore block_of_cyan;
public static BlockColore block_of_blue;
public static BlockColore block_of_indigo;
public static BlockColore block_of_purple;
public static BlockColore block_of_magenta;
public static BlockColore block_of_brown;
public static BlockColore block_of_grayscale;

//half slabs
public static BlockColoreSlab slab_of_red = new BlockColoreSlabHalf("slab_of_red");
public static BlockColoreSlab slab_of_reddish_orange = new BlockColoreSlabHalf("slab_of_reddish_orange");
public static BlockColoreSlab slab_of_orange = new BlockColoreSlabHalf("slab_of_orange");
public static BlockColoreSlab slab_of_orangish_yellow = new BlockColoreSlabHalf("slab_of_orangish_yellow");
public static BlockColoreSlab slab_of_yellow = new BlockColoreSlabHalf("slab_of_yellow");
public static BlockColoreSlab slab_of_yellowish_green = new BlockColoreSlabHalf("slab_of_yellowish_green");
public static BlockColoreSlab slab_of_green = new BlockColoreSlabHalf("slab_of_green");
public static BlockColoreSlab slab_of_cyan = new BlockColoreSlabHalf("slab_of_cyan");
public static BlockColoreSlab slab_of_blue = new BlockColoreSlabHalf("slab_of_blue");
public static BlockColoreSlab slab_of_indigo = new BlockColoreSlabHalf("slab_of_indigo");
public static BlockColoreSlab slab_of_purple = new BlockColoreSlabHalf("slab_of_purple");
public static BlockColoreSlab slab_of_magenta = new BlockColoreSlabHalf("slab_of_magenta");
public static BlockColoreSlab slab_of_brown = new BlockColoreSlabHalf("slab_of_brown");
public static BlockColoreSlab slab_of_grayscale = new BlockColoreSlabHalf("slab_of_grayscale");

//double slabs
public static BlockColoreSlab double_slab_of_red = new BlockColoreSlabDouble("double_slab_of_red");
public static BlockColoreSlab double_slab_of_reddish_orange = new BlockColoreSlabDouble("double_slab_of_reddish_orange");
public static BlockColoreSlab double_slab_of_orange = new BlockColoreSlabDouble("double_slab_of_orange");
public static BlockColoreSlab double_slab_of_orangish_yellow = new BlockColoreSlabDouble("double_slab_of_orangish_yellow");
public static BlockColoreSlab double_slab_of_yellow = new BlockColoreSlabDouble("double_slab_of_yellow");
public static BlockColoreSlab double_slab_of_yellowish_green = new BlockColoreSlabDouble("double_slab_of_yellowish_green");
public static BlockColoreSlab double_slab_of_green = new BlockColoreSlabDouble("double_slab_of_green");
public static BlockColoreSlab double_slab_of_cyan = new BlockColoreSlabDouble("double_slab_of_cyan");
public static BlockColoreSlab double_slab_of_blue = new BlockColoreSlabDouble("double_slab_of_blue");
public static BlockColoreSlab double_slab_of_indigo = new BlockColoreSlabDouble("double_slab_of_indigo");
public static BlockColoreSlab double_slab_of_purple = new BlockColoreSlabDouble("double_slab_of_purple");
public static BlockColoreSlab double_slab_of_magenta = new BlockColoreSlabDouble("double_slab_of_magenta");
public static BlockColoreSlab double_slab_of_brown = new BlockColoreSlabDouble("double_slab_of_brown");
public static BlockColoreSlab double_slab_of_grayscale = new BlockColoreSlabDouble("double_slab_of_grayscale");

//ore blocks	
public static BlockColoreOre essence_ore;

public static void registerBlocks() {
	//regular blocks
	GameRegistry.registerBlock(block_of_red = new BlockColore("block_of_red"), ItemBlockColore.class, "block_of_red");
	GameRegistry.registerBlock(block_of_reddish_orange = new BlockColore("block_of_reddish_orange"), ItemBlockColore.class, "block_of_reddish_orange");
	GameRegistry.registerBlock(block_of_orange = new BlockColore("block_of_orange"), ItemBlockColore.class, "block_of_orange");
	GameRegistry.registerBlock(block_of_orangish_yellow = new BlockColore("block_of_orangish_yellow"), ItemBlockColore.class, "block_of_orangish_yellow");
	GameRegistry.registerBlock(block_of_yellow = new BlockColore("block_of_yellow"), ItemBlockColore.class, "block_of_yellow");
	GameRegistry.registerBlock(block_of_yellowish_green = new BlockColore("block_of_yellowish_green"), ItemBlockColore.class, "block_of_yellowish_green");
	GameRegistry.registerBlock(block_of_green = new BlockColore("block_of_green"), ItemBlockColore.class, "block_of_green");
	GameRegistry.registerBlock(block_of_cyan = new BlockColore("block_of_cyan"), ItemBlockColore.class, "block_of_cyan");
	GameRegistry.registerBlock(block_of_blue = new BlockColore("block_of_blue"), ItemBlockColore.class, "block_of_blue");
	GameRegistry.registerBlock(block_of_indigo = new BlockColore("block_of_indigo"), ItemBlockColore.class, "block_of_indigo");
	GameRegistry.registerBlock(block_of_purple = new BlockColore("block_of_purple"), ItemBlockColore.class, "block_of_purple");
	GameRegistry.registerBlock(block_of_magenta = new BlockColore("block_of_magenta"), ItemBlockColore.class, "block_of_magenta");
	GameRegistry.registerBlock(block_of_brown = new BlockColore("block_of_brown"), ItemBlockColore.class, "block_of_brown");
	GameRegistry.registerBlock(block_of_grayscale = new BlockColore("block_of_grayscale"), ItemBlockColore.class, "block_of_grayscale");

	//half slabs
	GameRegistry.registerBlock(slab_of_red, ItemBlockColoreSlab.class, "slab_of_red", slab_of_red, double_slab_of_red);
	GameRegistry.registerBlock(slab_of_reddish_orange, ItemBlockColoreSlab.class, "slab_of_reddish_orange", slab_of_reddish_orange, double_slab_of_reddish_orange);
	GameRegistry.registerBlock(slab_of_orange, ItemBlockColoreSlab.class, "slab_of_orange", slab_of_orange, double_slab_of_orange);
	GameRegistry.registerBlock(slab_of_orangish_yellow, ItemBlockColoreSlab.class, "slab_of_orangish_yellow", slab_of_orangish_yellow, double_slab_of_orangish_yellow);
	GameRegistry.registerBlock(slab_of_yellow, ItemBlockColoreSlab.class, "slab_of_yellow", slab_of_yellow, double_slab_of_yellow);
	GameRegistry.registerBlock(slab_of_yellowish_green, ItemBlockColoreSlab.class, "slab_of_yellowish_green", slab_of_yellowish_green, double_slab_of_yellowish_green);
	GameRegistry.registerBlock(slab_of_green, ItemBlockColoreSlab.class, "slab_of_green", slab_of_green, double_slab_of_green);
	GameRegistry.registerBlock(slab_of_cyan, ItemBlockColoreSlab.class, "slab_of_cyan", slab_of_cyan, double_slab_of_cyan);
	GameRegistry.registerBlock(slab_of_blue, ItemBlockColoreSlab.class, "slab_of_blue", slab_of_blue, double_slab_of_blue);
	GameRegistry.registerBlock(slab_of_indigo, ItemBlockColoreSlab.class, "slab_of_indigo", slab_of_indigo, double_slab_of_indigo);
	GameRegistry.registerBlock(slab_of_purple, ItemBlockColoreSlab.class, "slab_of_purple", slab_of_purple, double_slab_of_purple);
	GameRegistry.registerBlock(slab_of_magenta, ItemBlockColoreSlab.class, "slab_of_magenta", slab_of_magenta, double_slab_of_magenta);
	GameRegistry.registerBlock(slab_of_brown, ItemBlockColoreSlab.class, "slab_of_brown", slab_of_brown, double_slab_of_brown);
	GameRegistry.registerBlock(slab_of_grayscale, ItemBlockColoreSlab.class, "slab_of_grayscale", slab_of_grayscale, double_slab_of_grayscale);

	//double slabs
	GameRegistry.registerBlock(double_slab_of_red, ItemBlockColoreSlab.class, "double_slab_of_red", slab_of_red, double_slab_of_red);
	GameRegistry.registerBlock(double_slab_of_reddish_orange, ItemBlockColoreSlab.class, "double_slab_of_reddish_orange", slab_of_reddish_orange, double_slab_of_reddish_orange);
	GameRegistry.registerBlock(double_slab_of_orange, ItemBlockColoreSlab.class, "double_slab_of_orange", slab_of_orange, double_slab_of_orange);
	GameRegistry.registerBlock(double_slab_of_orangish_yellow, ItemBlockColoreSlab.class, "double_slab_of_orangish_yellow", slab_of_orangish_yellow, double_slab_of_orangish_yellow);
	GameRegistry.registerBlock(double_slab_of_yellow, ItemBlockColoreSlab.class, "double_slab_of_yellow", slab_of_yellow, double_slab_of_yellow);
	GameRegistry.registerBlock(double_slab_of_yellowish_green, ItemBlockColoreSlab.class, "double_slab_of_yellowish_green", slab_of_yellowish_green, double_slab_of_yellowish_green);
	GameRegistry.registerBlock(double_slab_of_green, ItemBlockColoreSlab.class, "double_slab_of_green", slab_of_green, double_slab_of_green);
	GameRegistry.registerBlock(double_slab_of_cyan, ItemBlockColoreSlab.class, "double_slab_of_cyan", slab_of_cyan, double_slab_of_cyan);
	GameRegistry.registerBlock(double_slab_of_blue, ItemBlockColoreSlab.class, "double_slab_of_blue", slab_of_blue, double_slab_of_blue);
	GameRegistry.registerBlock(double_slab_of_indigo, ItemBlockColoreSlab.class, "double_slab_of_indigo", slab_of_indigo, double_slab_of_indigo);
	GameRegistry.registerBlock(double_slab_of_purple, ItemBlockColoreSlab.class, "double_slab_of_purple", slab_of_purple, double_slab_of_purple);
	GameRegistry.registerBlock(double_slab_of_magenta, ItemBlockColoreSlab.class, "double_slab_of_magenta", slab_of_magenta, double_slab_of_magenta);
	GameRegistry.registerBlock(double_slab_of_brown, ItemBlockColoreSlab.class, "double_slab_of_brown", slab_of_brown, double_slab_of_brown);
	GameRegistry.registerBlock(double_slab_of_grayscale, ItemBlockColoreSlab.class, "double_slab_of_grayscale", slab_of_grayscale, double_slab_of_grayscale);

	GameRegistry.registerBlock(essence_ore = new BlockColoreOre("essence_ore"), ItemBlockColore.class, "essence_ore");
}
}

 

 

//client.render package//

 

BlockRenders.java (renamed from BlockRenderRegistry.java)

	package com.supergeniuszeb.colore.client.render;

import com.supergeniuszeb.colore.Reference;
import com.supergeniuszeb.colore.common.init.ModBlocks;
import com.supergeniuszeb.colore.utility.ModUtilities;

import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.registry.GameRegistry;

//All this handles are the item-block models, not the actual block models, which are
//defined in the .json files.
public class BlockRenders {

//This method is called by the registerRenders method every time it adds an item-block model without metadata specified.
public static void registerRender(Block block) {
	Item item = Item.getItemFromBlock(block);
	Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(block), 0, new ModelResourceLocation(block.getRegistryName(), "inventory"));
}

//This method is called by the init method every time it adds an item-block model with metadata specified.
public static void registerRender(Block block, int meta, String metaName) {
	Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(block), meta, new ModelResourceLocation(block.getRegistryName() + "_" + metaName, "inventory"));
}

public static void preInit() {
	for (String color : ModUtilities.colorList) {
		for (String shade : ModUtilities.shadeList) {
			for (String blockType : ModUtilities.blockTypeList) {
				//standard blocks, half slabs, & double slabs
				ModelBakery.registerItemVariants(Item.getItemFromBlock(GameRegistry.findBlock(Reference.MOD_ID, blockType + "_of_" + color)), new ResourceLocation(Reference.MOD_ID, blockType + "_of_" + color + "_" + shade));
			}
		}
	}
	for (String color : ModUtilities.baseColorList) {
		//ore blocks
		ModelBakery.registerItemVariants(Item.getItemFromBlock(ModBlocks.essence_ore), new ResourceLocation(Reference.MOD_ID, "essence_ore_" + color));
	}
}

public static void init() {
	int i = 0;
	for (String shade : ModUtilities.shadeList) {
		for (String color : ModUtilities.colorList) {
			for (String blockType : ModUtilities.blockTypeList) {
				//standard blocks, half slabs, & double slabs
				registerRender(GameRegistry.findBlock(Reference.MOD_ID, blockType + "_of_" + color), i, shade);
			}
		}
		i++;
	}
	i = 0;
	for (String color : ModUtilities.baseColorList) {
		//ore blocks
		registerRender(ModBlocks.essence_ore, i, color);
		i++;
	}
}

}

 

 

//utility package//

 

ModUtilities.java

package com.supergeniuszeb.colore.utility;

/*
* A class used for storing various arrays and such that are convenient for things
* like iterating through the list of block colors in a for each loop to reduce the
* size of code when performing various functions.
*/
public class ModUtilities {

/*
 * The list of block types in the mod.
 */
public static String[] blockTypeList = new String[] {
	"block", "slab", "double_slab"
};

/*
 * A simple list of the half slab types.
 * Currently unused.
 */
public static String[] halfSlabTypeList = new String[] {
	"bottom", "top"
};

/*
 * The list of shades for the blocks and items in the mod.
 */
public static String[] shadeList = new String[] {
	"normal", "light", "lighter", "dark", "darker"
};

/*
 * The list of colors for the blocks and items in the mod.
 */
public static String[] colorList = new String[] {
	"red", "reddish_orange", "orange", "orangish_yellow", "yellow",
	"yellowish_green", "green", "cyan", "blue", "indigo", "purple",
	"magenta", "brown", "grayscale"
};

/*
 * The list of base (or ore) colors in the mod.
 */
public static String[] baseColorList = new String[] {
	"red", "yellow", "blue", "brown", "white", "black"
};
}

 

 

 

 

Original Post:

 

I'm trying to add slabs with metadata to my mod, but so far I'm not having too much success. I know how slabs work in game (they're 2 different blocks: a half-slab block with at least 2 blockstates and a double slab block that's basically just a normal block that drops 2 of the former) and that you're supposed to have an abstract slab class (BlockColoreSlab), a half slab class (BlockColoreSlabHalf), a double slab class (BlockColoreSlabDouble), and an item-block class (ItemBlockColoreSlab), but I have no idea how to get them working right. I have the metadata on the slabs set up with 2 properties: "SHADE" and "HALF". "SHADE" has 5 different values: normal, light, lighter, dark, and darker, and "HALF" has, of course, just 2 values and determines whether the block is a top slab of bottom slab (if it is even a half slab.) So for example I'm trying to add a Slab of Red that uses the metadata to determine both the color and which type of slab it is. (Values 0-4 are bottom slabs and 5-9 are top slabs. Double slabs just have values 0-4.) At this point I haven't created any model, texture, or other .json files for any of the slabs, and neither have I put them in the .lang file, as I'm just trying to get them functional right now.

 

Here's what happens when I launch the game:

The game doesn't crash, and the half-slabs can be placed like regular slabs, and have the same hitboxes. However, they can't be stacked into double slabs. Both the regular and the double slabs show up in the creative tab I have created for them, though the double slabs shouldn't be there. Both the half and double variants of the slabs have the same name in the creative menu. (For example, the slab_of_red with a SHADE state of "NORMAL" shows as tile.slab_of_red.normal.name, and its double variant shows with the exact same name, but when viewed in F3+H mode, you can see their actual code names of colore:slab_of_red and colore:slab_of_red_double... I'm not sure if this is normal or not, as I have not tried to create any .json files or textures yet.)

 

Anyway, here are the slab classes and the classes I use to register my blocks. If you need to see any more, just let me know. See the top of the post for the current state of how things are working. (I'll update it as I fix things and make progress...)

 

BlockColoreSlab (abstract slab class):

package com.supergeniuszeb.colore.common.blocks;

import net.minecraft.block.Block;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import com.supergeniuszeb.colore.common.registry.CreativeTabRegistry;

//An abstract class for both half-slabs and full/double slabs.
public abstract class BlockColoreSlab extends BlockSlab implements IMetaBlockName{

public BlockColoreSlab(String unlocalizedName) {
	super(Material.rock);
	this.setHardness(1.5f);
	this.setHarvestLevel("pickaxe", 0);
	this.setResistance(10.0f);
	this.setUnlocalizedName(unlocalizedName);
	this.useNeighborBrightness = !this.isDouble();
	if (!this.isDouble()) {
            this.setCreativeTab(CreativeTabRegistry.slabTab);
        }

	//Sets default state depending on whether block is a half-slab or double-slab.
	IBlockState blockState = this.blockState.getBaseState();
        blockState = blockState.withProperty(SHADE, EnumShade.NORMAL);
        if (!this.isDouble()) {
            blockState = blockState.withProperty(HALF, EnumBlockHalf.BOTTOM);
        }

        this.setDefaultState(blockState);
}

public enum EnumShade implements IStringSerializable {
	NORMAL(0, "normal"),
	LIGHT(1, "light"),
	LIGHTER(2, "lighter"),
	DARK(3, "dark"),
	DARKER(4, "darker");

	private int ID;
	private String name;

	private EnumShade(int ID, String name) {
		this.ID = ID;
		this.name = name;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		return getName();
	}

	public int getID() {
        return ID;
    }

}

//The shade ("light", "dark", etc.) of the slab. The "HALF" property is defined in the vanilla BlockSlab class so I don't need to make my own.
public static final PropertyEnum SHADE = PropertyEnum.create("shade", BlockColoreSlab.EnumShade.class);

//Function to get the variant property created above based on the item.
@Override
public final Object getVariant(final ItemStack itemstack) {
	return itemstack.getMetadata();
}

//Function to get the variant property.
@Override
public final IProperty getVariantProperty() {
	return SHADE;
}

@SideOnly(Side.CLIENT)
    @Override
    public final net.minecraft.item.Item getItem(
        final net.minecraft.world.World world,
        final net.minecraft.util.BlockPos blockPos) {
        String blockId = this.getUnlocalizedName();
        return Item.getItemFromBlock(Block.getBlockFromName(blockId));
    }

@Override
protected BlockState createBlockState() {
	return new BlockState(this, new IProperty[] {SHADE, HALF});
}

//Converts an IBlockState into metadata.
@Override
public IBlockState getStateFromMeta(int meta) {

	//A blockState is created, which is assigned the SHADE property depending on its metadata, as well as the HALF property, if it is a half-slab.
	IBlockState blockState = this.getDefaultState();

	if (!this.isDouble()) { //If the block is a BlockColoreHalfSlab
		switch (meta) {
			case 0:
				blockState = blockState.withProperty(SHADE, EnumShade.NORMAL).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break; //Note-to-self: NEVER EVER FORGET TO USE THIS IF RETURN STATEMENTS AREN'T INVOLVED!
			case 1:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHT).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break;
			case 2:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHTER).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break;
			case 3:
				blockState = blockState.withProperty(SHADE, EnumShade.DARK).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break;
			case 4:
				blockState = blockState.withProperty(SHADE, EnumShade.DARKER).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break;
			case 5:
				blockState = blockState.withProperty(SHADE, EnumShade.NORMAL).withProperty(HALF, EnumBlockHalf.TOP);
				break;
			case 6:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHT).withProperty(HALF, EnumBlockHalf.TOP);
				break;
			case 7:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHTER).withProperty(HALF, EnumBlockHalf.TOP);
				break;
			case 8:
				blockState = blockState.withProperty(SHADE, EnumShade.DARK).withProperty(HALF, EnumBlockHalf.TOP);
				break;
			case 9:
				blockState = blockState.withProperty(SHADE, EnumShade.DARKER).withProperty(HALF, EnumBlockHalf.TOP);
				break;
			default:
				blockState = blockState.withProperty(SHADE, EnumShade.NORMAL).withProperty(HALF, EnumBlockHalf.BOTTOM);
				break;
		}
	} else { //If the block is a BlockColoreDoubleSlab
		switch (meta) {
			case 0:
				blockState = blockState.withProperty(SHADE, EnumShade.NORMAL);
				break;
			case 1:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHT);
				break;
			case 2:
				blockState = blockState.withProperty(SHADE, EnumShade.LIGHTER);
				break;
			case 3:
				blockState = blockState.withProperty(SHADE, EnumShade.DARK);
				break;
			case 4:
				blockState = blockState.withProperty(SHADE, EnumShade.DARKER);
				break;
			default:
				blockState = blockState.withProperty(SHADE, EnumShade.NORMAL);
				break;
		}
	}

	return blockState;
}

//Converts metadata into an IBlockState.
@Override
public int getMetaFromState(IBlockState state) {

    EnumShade shade = (EnumShade) state.getValue(SHADE);
    
    if (!this.isDouble()) {
    	EnumBlockHalf half = (EnumBlockHalf) state.getValue(HALF);
    	
    	//0-4 are bottom slabs, and 5-9 are the top slabs, so if the HALF property = top,
    	//then 5 is added to the ID integer assigned to the SHADE property. This is done
    	//to match up with how I've assigned the 9 different metadata values. (I hope
    	//this comment made sense so I don't come back later trying to find out why I did
    	//this and get disappointed with my former self's explanatory skills...)
    	if (half == EnumBlockHalf.TOP) {
    		return shade.getID() + 5; 
    	}
    }
    
    return shade.getID();
}

//This insures that  the meta block drops an item-block with the correct metadata when mined. This is
//somewhat trickier than with a regular block since you don't want to drop a "top" or "bottom" half slab.
//You only want to drop... well, just a slab! (Or more technically, a default, or bottom, half slab.
//Of course, if you're breaking a double-slab, it shouldn't drop a block with the HALF property at all.
@Override
public int damageDropped(IBlockState state) {
	if (!this.isDouble()) {
		//Using my neat math tricks in conjuction with how I've set up the 9 metadata values so that
		//0-4 are bottom slabs and 5-9 are top slabs.
		if (getMetaFromState(state) > 5) { //If the block is a top slab, then drop a bottom slab.
			return getMetaFromState(state) - 5;
		}
	}
	//If the block is a bottom slab or double slab, then drop a block with a metadata between 0-4.
	//The value of the SHADE property is assigned to the same 5 integers for both bottom half slabs
	//and double slabs, so this works. Hooray for clever metadata-blockstate-math-stuff!
    return getMetaFromState(state);
}

//Used to get the last part of the unlocalized name for the item-block.
//The structure of the unlocalized name is: tile.blockname.specialname.name
@Override
public String getSpecialName(ItemStack stack) {
	switch (stack.getItemDamage()) {
		case 0:
			return "normal";
		case 1:
			return "light";
		case 2:
			return "lighter";
		case 3:
			return "dark";
		case 4:
			return "darker";
		default:
			return "normal";
	}
}

@Override
    public final String getUnlocalizedName(final int metadata) {
        return this.getUnlocalizedName();
    }

//This ensures that the pick-block button (normally middle-click) will give
//an item-block with the correct metadata.
@Override
public ItemStack getPickBlock(MovingObjectPosition target, World world, BlockPos pos) {
    return new ItemStack(Item.getItemFromBlock(this), 1, this.getMetaFromState(world.getBlockState(pos)));
}

//WIP BEYOND THIS POINT

}

 

BlockColoreSlabHalf:

package com.supergeniuszeb.colore.common.blocks;

import net.minecraft.block.properties.IProperty;
import net.minecraft.item.ItemStack;

public class BlockColoreSlabHalf extends BlockColoreSlab {

public BlockColoreSlabHalf(String unlocalizedName) {
	super(unlocalizedName);
}

@Override
public boolean isDouble() {
	return false;
}

}

 

BlockColoreSlabDouble:

package com.supergeniuszeb.colore.common.blocks;

public class BlockColoreSlabDouble extends BlockColoreSlab {

public BlockColoreSlabDouble(String unlocalizedName) {
	super(unlocalizedName);
}

@Override
public boolean isDouble() {
	return true;
}
}

 

ItemBlockColoreSlab:

package com.supergeniuszeb.colore.common.blocks;

import java.util.ArrayList;
import java.util.List;

import com.supergeniuszeb.colore.common.registry.BlockRegistry;

import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemSlab;
import net.minecraft.item.ItemStack;

/*
* Wrapper class to make sure that GameRegistry.registerBlock() calls the right constructor.
*/
public class ItemBlockColoreSlab extends ItemSlab {

public ItemBlockColoreSlab(final Block block, final BlockColoreSlabHalf slab, final BlockColoreSlabDouble doubleSlab, final Boolean stacked) {
	super(block, slab, doubleSlab);
	this.setHasSubtypes(true);
        this.getSubBlocks(slabList, this, 5);
}

public int getMetadata(int damage)
    {
        return damage;
    }

@Override
    public String getUnlocalizedName(ItemStack stack) {
        return super.getUnlocalizedName(stack) + "." + ((IMetaBlockName)this.block).getSpecialName(stack);
    }

public static List slabList = new ArrayList<Item>(5) {};

	//This will add all the different metadata variations of the slabs
	//as "ItemStack"s to the slabList list. Used when adding metadata
	//blocks to the creative tabs.
	public void getSubBlocks(List slabList, Item item, int range) {
		for (int i = 0; i < range; ++i) {
            slabList.add(new ItemStack(item, 1, i));
        }
	}

}

 

(I've commented out the other slabs, since all I really need is to get the red slab working, and then I can just do copying-and-pasting for all the others.)

BlockRegistry (used to register instances of blocks):

package com.supergeniuszeb.colore.common.registry;

import net.minecraftforge.fml.common.registry.GameRegistry;

import com.supergeniuszeb.colore.common.blocks.BlockColore;
import com.supergeniuszeb.colore.common.blocks.BlockColoreOre;
import com.supergeniuszeb.colore.common.blocks.BlockColoreSlab;
import com.supergeniuszeb.colore.common.blocks.BlockColoreSlabDouble;
import com.supergeniuszeb.colore.common.blocks.BlockColoreSlabHalf;
import com.supergeniuszeb.colore.common.blocks.ItemBlockColore;
import com.supergeniuszeb.colore.common.blocks.ItemBlockColoreSlab;

public class BlockRegistry {

//regular blocks
public static BlockColore block_of_red;
public static BlockColore block_of_reddish_orange;
public static BlockColore block_of_orange;
public static BlockColore block_of_orangish_yellow;
public static BlockColore block_of_yellow;
public static BlockColore block_of_yellowish_green;
public static BlockColore block_of_green;
public static BlockColore block_of_cyan;
public static BlockColore block_of_blue;
public static BlockColore block_of_indigo;
public static BlockColore block_of_purple;
public static BlockColore block_of_magenta;
public static BlockColore block_of_brown;
public static BlockColore block_of_grayscale;

//half slabs
public static BlockColoreSlab slab_of_red = new BlockColoreSlabHalf("slab_of_red");
/*	public static BlockColoreSlabHalf slab_of_reddish_orange;
public static BlockColoreSlabHalf slab_of_orange;
public static BlockColoreSlabHalf slab_of_orangish_yellow;
public static BlockColoreSlabHalf slab_of_yellow;
public static BlockColoreSlabHalf slab_of_yellowish_green;
public static BlockColoreSlabHalf slab_of_green;
public static BlockColoreSlabHalf slab_of_cyan;
public static BlockColoreSlabHalf slab_of_blue;
public static BlockColoreSlabHalf slab_of_indigo;
public static BlockColoreSlabHalf slab_of_purple;
public static BlockColoreSlabHalf slab_of_magenta;
public static BlockColoreSlabHalf slab_of_brown;
public static BlockColoreSlabHalf slab_of_grayscale;
*/
//double slabs
public static BlockColoreSlab slab_of_red_double = new BlockColoreSlabDouble("slab_of_red_double");
/*public static BlockColoreSlabDouble slab_of_reddish_orange_double;
public static BlockColoreSlabDouble slab_of_orange_double;
public static BlockColoreSlabDouble slab_of_orangish_yellow_double;
public static BlockColoreSlabDouble slab_of_yellow_double;
public static BlockColoreSlabDouble slab_of_yellowish_green_double;
public static BlockColoreSlabDouble slab_of_green_double;
public static BlockColoreSlabDouble slab_of_cyan_double;
public static BlockColoreSlabDouble slab_of_blue_double;
public static BlockColoreSlabDouble slab_of_indigo_double;
public static BlockColoreSlabDouble slab_of_purple_double;
public static BlockColoreSlabDouble slab_of_magenta_double;
public static BlockColoreSlabDouble slab_of_brown_double;
public static BlockColoreSlabDouble slab_of_grayscale_double;*/

//ore blocks	
public static BlockColoreOre essence_ore;

public static void registerBlocks() {
	//regular blocks
	GameRegistry.registerBlock(block_of_red = new BlockColore("block_of_red"), ItemBlockColore.class, "block_of_red");
	GameRegistry.registerBlock(block_of_reddish_orange = new BlockColore("block_of_reddish_orange"), ItemBlockColore.class, "block_of_reddish_orange");
	GameRegistry.registerBlock(block_of_orange = new BlockColore("block_of_orange"), ItemBlockColore.class, "block_of_orange");
	GameRegistry.registerBlock(block_of_orangish_yellow = new BlockColore("block_of_orangish_yellow"), ItemBlockColore.class, "block_of_orangish_yellow");
	GameRegistry.registerBlock(block_of_yellow = new BlockColore("block_of_yellow"), ItemBlockColore.class, "block_of_yellow");
	GameRegistry.registerBlock(block_of_yellowish_green = new BlockColore("block_of_yellowish_green"), ItemBlockColore.class, "block_of_yellowish_green");
	GameRegistry.registerBlock(block_of_green = new BlockColore("block_of_green"), ItemBlockColore.class, "block_of_green");
	GameRegistry.registerBlock(block_of_cyan = new BlockColore("block_of_cyan"), ItemBlockColore.class, "block_of_cyan");
	GameRegistry.registerBlock(block_of_blue = new BlockColore("block_of_blue"), ItemBlockColore.class, "block_of_blue");
	GameRegistry.registerBlock(block_of_indigo = new BlockColore("block_of_indigo"), ItemBlockColore.class, "block_of_indigo");
	GameRegistry.registerBlock(block_of_purple = new BlockColore("block_of_purple"), ItemBlockColore.class, "block_of_purple");
	GameRegistry.registerBlock(block_of_magenta = new BlockColore("block_of_magenta"), ItemBlockColore.class, "block_of_magenta");
	GameRegistry.registerBlock(block_of_brown = new BlockColore("block_of_brown"), ItemBlockColore.class, "block_of_brown");
	GameRegistry.registerBlock(block_of_grayscale = new BlockColore("block_of_grayscale"), ItemBlockColore.class, "block_of_grayscale");

	//half slabs
	GameRegistry.registerBlock(slab_of_red, ItemBlockColoreSlab.class, "slab_of_red", slab_of_red, slab_of_red_double, false);
	/*GameRegistry.registerBlock(slab_of_reddish_orange = new BlockColoreSlabHalf("slab_of_reddish_orange"), ItemBlockColoreSlab.class, "slab_of_reddish_orange");
	GameRegistry.registerBlock(slab_of_orange = new BlockColoreSlabHalf("slab_of_orange"), ItemBlockColoreSlab.class, "slab_of_orange");
	GameRegistry.registerBlock(slab_of_orangish_yellow = new BlockColoreSlabHalf("slab_of_orangish_yellow"), ItemBlockColoreSlab.class, "slab_of_orangish_yellow");
	GameRegistry.registerBlock(slab_of_yellow = new BlockColoreSlabHalf("slab_of_yellow"), ItemBlockColoreSlab.class, "slab_of_yellow");
	GameRegistry.registerBlock(slab_of_yellowish_green = new BlockColoreSlabHalf("slab_of_yellowish_green"), ItemBlockColoreSlab.class, "slab_of_yellowish_green");
	GameRegistry.registerBlock(slab_of_green = new BlockColoreSlabHalf("slab_of_green"), ItemBlockColoreSlab.class, "slab_of_green");
	GameRegistry.registerBlock(slab_of_cyan = new BlockColoreSlabHalf("slab_of_cyan"), ItemBlockColoreSlab.class, "slab_of_cyan");
	GameRegistry.registerBlock(slab_of_blue = new BlockColoreSlabHalf("slab_of_blue"), ItemBlockColoreSlab.class, "slab_of_blue");
	GameRegistry.registerBlock(slab_of_indigo = new BlockColoreSlabHalf("slab_of_indigo"), ItemBlockColoreSlab.class, "slab_of_indigo");
	GameRegistry.registerBlock(slab_of_purple = new BlockColoreSlabHalf("slab_of_purple"), ItemBlockColoreSlab.class, "slab_of_purple");
	GameRegistry.registerBlock(slab_of_magenta = new BlockColoreSlabHalf("slab_of_magenta"), ItemBlockColoreSlab.class, "slab_of_magenta");
	GameRegistry.registerBlock(slab_of_brown = new BlockColoreSlabHalf("slab_of_brown"), ItemBlockColoreSlab.class, "slab_of_brown");
	GameRegistry.registerBlock(slab_of_grayscale = new BlockColoreSlabHalf("slab_of_grayscale"), ItemBlockColoreSlab.class, "slab_of_grayscale");
	*/
	//double slabs
	GameRegistry.registerBlock(slab_of_red_double, ItemBlockColoreSlab.class, "slab_of_red_double", slab_of_red, slab_of_red_double, true);
	/*GameRegistry.registerBlock(slab_of_reddish_orange_double = new BlockColoreSlabDouble("slab_of_reddish_orange_double"), ItemBlockColoreSlab.class, "slab_of_reddish_orange_double");
	GameRegistry.registerBlock(slab_of_orange_double = new BlockColoreSlabDouble("slab_of_orange_double"), ItemBlockColoreSlab.class, "slab_of_orange_double");
	GameRegistry.registerBlock(slab_of_orangish_yellow_double = new BlockColoreSlabDouble("slab_of_orangish_yellow_double"), ItemBlockColoreSlab.class, "slab_of_orangish_yellow_double");
	GameRegistry.registerBlock(slab_of_yellow_double = new BlockColoreSlabDouble("slab_of_yellow_double"), ItemBlockColoreSlab.class, "slab_of_yellow_double");
	GameRegistry.registerBlock(slab_of_yellowish_green_double = new BlockColoreSlabDouble("slab_of_yellowish_green_double"), ItemBlockColoreSlab.class, "slab_of_yellowish_green_double");
	GameRegistry.registerBlock(slab_of_green_double = new BlockColoreSlabDouble("slab_of_green_double"), ItemBlockColoreSlab.class, "slab_of_green_double");
	GameRegistry.registerBlock(slab_of_cyan_double = new BlockColoreSlabDouble("slab_of_cyan_double"), ItemBlockColoreSlab.class, "slab_of_cyan_double");
	GameRegistry.registerBlock(slab_of_blue_double = new BlockColoreSlabDouble("slab_of_blue_double"), ItemBlockColoreSlab.class, "slab_of_blue_double");
	GameRegistry.registerBlock(slab_of_indigo_double = new BlockColoreSlabDouble("slab_of_indigo_double"), ItemBlockColoreSlab.class, "slab_of_indigo_double");
	GameRegistry.registerBlock(slab_of_purple_double = new BlockColoreSlabDouble("slab_of_purple_double"), ItemBlockColoreSlab.class, "slab_of_purple_double");
	GameRegistry.registerBlock(slab_of_magenta_double = new BlockColoreSlabDouble("slab_of_magenta_double"), ItemBlockColoreSlab.class, "slab_of_magenta_double");
	GameRegistry.registerBlock(slab_of_brown_double = new BlockColoreSlabDouble("slab_of_brown_double"), ItemBlockColoreSlab.class, "slab_of_brown_double");
	GameRegistry.registerBlock(slab_of_grayscale_double = new BlockColoreSlabDouble("slab_of_grayscale_double"), ItemBlockColoreSlab.class, "slab_of_grayscale_double");
*/
	GameRegistry.registerBlock(essence_ore = new BlockColoreOre("essence_ore"), ItemBlockColore.class, "essence_ore");
}
}

 

BlockRenderRegistry (used to register block models and item-block models... I am aware I haven't registered the slab models or anything yet, but nothing in this class affects the functionality of the blocks, so I'm not going to add anything here until the slabs work as intended and all that's left is the rendering side of things.):

	package com.supergeniuszeb.colore.client.render;

import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;

import com.supergeniuszeb.colore.Reference;
import com.supergeniuszeb.colore.common.registry.BlockRegistry;
import com.supergeniuszeb.colore.utility.ModUtilities;

//All this handles are the item-block models, not the actual block models, which are
//defined in the .json files.
public class BlockRenderRegistry {

//This method is called by the registerRenders method every time it adds an item-block model.
public static void registerRender(Block block) {
	Item item = Item.getItemFromBlock(block);
	Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(block), 0, new ModelResourceLocation(Reference.MOD_ID + ":" + item.getUnlocalizedName().substring(5), "inventory"));
}

//This method is called by the init method every time it adds a meta item-block model.
public static void registerRender(Block block, int meta, String fileName) {
	Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(block), meta, new ModelResourceLocation(Reference.MOD_ID + ":" + fileName, "inventory"));
}

public static void preInit() {

	for (String shade : ModUtilities.shadeList) {
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_red), new ResourceLocation(Reference.MOD_ID, "block_of_red_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_reddish_orange), new ResourceLocation(Reference.MOD_ID, "block_of_reddish_orange_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_orange), new ResourceLocation(Reference.MOD_ID, "block_of_orange_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_orangish_yellow), new ResourceLocation(Reference.MOD_ID, "block_of_orangish_yellow_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_yellow), new ResourceLocation(Reference.MOD_ID, "block_of_yellow_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_yellowish_green), new ResourceLocation(Reference.MOD_ID, "block_of_yellowish_green_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_green), new ResourceLocation(Reference.MOD_ID, "block_of_green_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_cyan), new ResourceLocation(Reference.MOD_ID, "block_of_cyan_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_blue), new ResourceLocation(Reference.MOD_ID, "block_of_blue_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_indigo), new ResourceLocation(Reference.MOD_ID, "block_of_indigo_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_purple), new ResourceLocation(Reference.MOD_ID, "block_of_purple_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_magenta), new ResourceLocation(Reference.MOD_ID, "block_of_magenta_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_brown), new ResourceLocation(Reference.MOD_ID, "block_of_brown_" + shade));
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.block_of_grayscale), new ResourceLocation(Reference.MOD_ID, "block_of_grayscale_" + shade));
	}

	for (String color : ModUtilities.baseColorList) {
		ModelBakery.registerItemVariants(Item.getItemFromBlock(BlockRegistry.essence_ore), new ResourceLocation(Reference.MOD_ID, "essence_ore_" + color));
	}
}

public static void init() {

	int i = 0;
	for (String shade : ModUtilities.shadeList) {
		registerRender(BlockRegistry.block_of_red, i, "block_of_red_" + shade);
		registerRender(BlockRegistry.block_of_reddish_orange, i, "block_of_reddish_orange_" + shade);
		registerRender(BlockRegistry.block_of_orange, i, "block_of_orange_" + shade);
		registerRender(BlockRegistry.block_of_orangish_yellow, i, "block_of_orangish_yellow_" + shade);
		registerRender(BlockRegistry.block_of_yellow, i, "block_of_yellow_" + shade);
		registerRender(BlockRegistry.block_of_yellowish_green, i, "block_of_yellowish_green_" + shade);
		registerRender(BlockRegistry.block_of_green, i, "block_of_green_" + shade);
		registerRender(BlockRegistry.block_of_cyan, i, "block_of_cyan_" + shade);
		registerRender(BlockRegistry.block_of_blue, i, "block_of_blue_" + shade);
		registerRender(BlockRegistry.block_of_indigo, i, "block_of_indigo_" + shade);
		registerRender(BlockRegistry.block_of_purple, i, "block_of_purple_" + shade);
		registerRender(BlockRegistry.block_of_magenta, i, "block_of_magenta_" + shade);
		registerRender(BlockRegistry.block_of_brown, i, "block_of_brown_" + shade);
		registerRender(BlockRegistry.block_of_grayscale, i, "block_of_grayscale_" + shade);
		i++;
	}

	i = 0;
	for (String color : ModUtilities.baseColorList) {
		registerRender(BlockRegistry.essence_ore, i, "essence_ore_" + color);
		i++;
	}
}

}

 

If you need to see any other classes, just let me know and I'll update this post.

 

Colore - The mod that adds monochrome blocks in every color of the rainbow!

http://www.minecraftforge.net/forum/index.php?topic=35149

 

If you're looking to learn how to make mods for 1.9.4, I wrote a helpful article with links to a lot of useful resources for learning Minecraft 1.9.4 modding!

 

http://supergeniuszeb.com/mods/a-helpful-list-of-minecraft-1-9-4-modding-resources/

Posted

Are you sure that you need BlockSlabHalf and BlockSlabDouble? I'm not seeing such an arrangement in Vanilla slabs. It sounds like your mechanism for changing one into the other is incomplete.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

  • 1 month later...
Posted

...And, 2 months later, after a lot of time being busy and being unable to work on my mod, I have recently been able to get my slabs working! Yay! ;D

 

Are you sure that you need BlockSlabHalf and BlockSlabDouble? I'm not seeing such an arrangement in Vanilla slabs. It sounds like your mechanism for changing one into the other is incomplete.

Vanilla does have similar classes... see BlockHalfStoneSlab and BlockDoubleStoneSlab.

Hi

 

Look in ItemSlab.onItemUse() to see how vanilla turns two half-slabs into a whole slab

 

-TGG

 

Thanks for the suggestion! After looking around in the ItemSlab class I was able to figure out how to get the half-slabs and double-slabs to be associated with each other, and I also learned quite a bit about how the slabs and a lot of other Minecraft code works in the process. (Discovered ItemSlab's this.singleSlab, which I had to indirectly access the values by creating a private variable in my ItemBlockColoreSlab class which I assigned the value of this.singleSlab, and then created setter & getter methods so I could easily-ish convert between a double slab as input in a method to its single slab counterpart.) I also cleaned up and simplified a lot of my code (thanks for adding the getRegistryName() & findBlock() methods, Forge team) and have a much better (but still not yet perfect) understanding of the Minecraft/Forge code.

 

For those who are having the same problem as me, I will update the main post with my new code, which I think would work as a better template for slabs with additional metadata/blockstates than the current 1.8 slabs tutorial on these forums. Note that I have renamed BlockRegistry.java & BlockRenderRegistry.java to ModBlocks.java & BlockRenders respectively, since those are more in line with the standard naming conventions and I think they make more sense than what I had before.

 

I would like to note that I am not fully satisfied with how I handle getting the name of a double slab's single/half slab counterpart. (See my comments in the updated code.) It feels a little indirect & hacky to me, and if anyone has any suggestions for a better way, please let me know. I really want my code to be clean and not use hacky, indirect ways of getting things to work.

Colore - The mod that adds monochrome blocks in every color of the rainbow!

http://www.minecraftforge.net/forum/index.php?topic=35149

 

If you're looking to learn how to make mods for 1.9.4, I wrote a helpful article with links to a lot of useful resources for learning Minecraft 1.9.4 modding!

 

http://supergeniuszeb.com/mods/a-helpful-list-of-minecraft-1-9-4-modding-resources/

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • It is 1.12.2 - I have no idea if there is a 1.12 pack
    • Okay, but does the modpack works with 1.12 or just with 1.12.2, because I need the Forge client specifically for Minecraft 1.12, not 1.12.2
    • Version 1.19 - Forge 41.0.63 I want to create a wolf entity that I can ride, so far it seems to be working, but the problem is that when I get on the wolf, I can’t control it. I then discovered that the issue is that the server doesn’t detect that I’m riding the wolf, so I’m struggling with synchronization. However, it seems to not be working properly. As I understand it, the server receives the packet but doesn’t register it correctly. I’m a bit new to Java, and I’ll try to provide all the relevant code and prints *The comments and prints are translated by chatgpt since they were originally in Spanish* Thank you very much in advance No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. MountableWolfEntity package com.vals.valscraft.entity; import com.vals.valscraft.network.MountSyncPacket; import com.vals.valscraft.network.NetworkHandler; import net.minecraft.client.Minecraft; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.Entity; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.network.PacketDistributor; public class MountableWolfEntity extends Wolf { private boolean hasSaddle; private static final EntityDataAccessor<Byte> DATA_ID_FLAGS = SynchedEntityData.defineId(MountableWolfEntity.class, EntityDataSerializers.BYTE); public MountableWolfEntity(EntityType<? extends Wolf> type, Level level) { super(type, level); this.hasSaddle = false; } @Override protected void defineSynchedData() { super.defineSynchedData(); this.entityData.define(DATA_ID_FLAGS, (byte)0); } public static AttributeSupplier.Builder createAttributes() { return Wolf.createAttributes() .add(Attributes.MAX_HEALTH, 20.0) .add(Attributes.MOVEMENT_SPEED, 0.3); } @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.getItem() == Items.SADDLE && !this.hasSaddle()) { if (!player.isCreative()) { itemstack.shrink(1); } this.setSaddle(true); return InteractionResult.SUCCESS; } else if (!level.isClientSide && this.hasSaddle()) { player.startRiding(this); MountSyncPacket packet = new MountSyncPacket(true); // 'true' means the player is mounted NetworkHandler.CHANNEL.sendToServer(packet); // Ensure the server handles the packet return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void travel(Vec3 travelVector) { if (this.isVehicle() && this.getControllingPassenger() instanceof Player) { System.out.println("The wolf has a passenger."); System.out.println("The passenger is a player."); Player player = (Player) this.getControllingPassenger(); // Ensure the player is the controller this.setYRot(player.getYRot()); this.yRotO = this.getYRot(); this.setXRot(player.getXRot() * 0.5F); this.setRot(this.getYRot(), this.getXRot()); this.yBodyRot = this.getYRot(); this.yHeadRot = this.yBodyRot; float forward = player.zza; float strafe = player.xxa; if (forward <= 0.0F) { forward *= 0.25F; } this.flyingSpeed = this.getSpeed() * 0.1F; this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 1.5F); this.setDeltaMovement(new Vec3(strafe, travelVector.y, forward).scale(this.getSpeed())); this.calculateEntityAnimation(this, false); } else { // The wolf does not have a passenger or the passenger is not a player System.out.println("No player is mounted, or the passenger is not a player."); super.travel(travelVector); } } public boolean hasSaddle() { return this.hasSaddle; } public void setSaddle(boolean hasSaddle) { this.hasSaddle = hasSaddle; } @Override protected void dropEquipment() { super.dropEquipment(); if (this.hasSaddle()) { this.spawnAtLocation(Items.SADDLE); this.setSaddle(false); } } @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.START) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); if (server != null) { for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player.isPassenger() && player.getVehicle() instanceof MountableWolfEntity) { MountableWolfEntity wolf = (MountableWolfEntity) player.getVehicle(); System.out.println("Tick: " + player.getName().getString() + " is correctly mounted on " + wolf); } } } } } private boolean lastMountedState = false; @Override public void tick() { super.tick(); if (!this.level.isClientSide) { // Only on the server boolean isMounted = this.isVehicle() && this.getControllingPassenger() instanceof Player; // Only print if the state changed if (isMounted != lastMountedState) { if (isMounted) { Player player = (Player) this.getControllingPassenger(); // Verify the passenger is a player System.out.println("Server: Player " + player.getName().getString() + " is now mounted."); } else { System.out.println("Server: The wolf no longer has a passenger."); } lastMountedState = isMounted; } } } @Override public void addPassenger(Entity passenger) { super.addPassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(true)); } } } @Override public void removePassenger(Entity passenger) { super.removePassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is no longer mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(false)); } } } @Override public boolean isControlledByLocalInstance() { Entity entity = this.getControllingPassenger(); return entity instanceof Player; } @Override public void positionRider(Entity passenger) { if (this.hasPassenger(passenger)) { double xOffset = Math.cos(Math.toRadians(this.getYRot() + 90)) * 0.4; double zOffset = Math.sin(Math.toRadians(this.getYRot() + 90)) * 0.4; passenger.setPos(this.getX() + xOffset, this.getY() + this.getPassengersRidingOffset() + passenger.getMyRidingOffset(), this.getZ() + zOffset); } } } MountSyncPacket package com.vals.valscraft.network; import com.vals.valscraft.entity.MountableWolfEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class MountSyncPacket { private final boolean isMounted; public MountSyncPacket(boolean isMounted) { this.isMounted = isMounted; } public void encode(FriendlyByteBuf buffer) { buffer.writeBoolean(isMounted); } public static MountSyncPacket decode(FriendlyByteBuf buffer) { return new MountSyncPacket(buffer.readBoolean()); } public void handle(NetworkEvent.Context context) { context.enqueueWork(() -> { ServerPlayer player = context.getSender(); // Get the player from the context if (player != null) { // Verifies if the player has dismounted if (!isMounted) { Entity vehicle = player.getVehicle(); if (vehicle instanceof MountableWolfEntity wolf) { // Logic to remove the player as a passenger wolf.removePassenger(player); System.out.println("Server: Player " + player.getName().getString() + " is no longer mounted."); } } } }); context.setPacketHandled(true); // Marks the packet as handled } } networkHandler package com.vals.valscraft.network; import com.vals.valscraft.valscraft; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class NetworkHandler { private static final String PROTOCOL_VERSION = "1"; public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(valscraft.MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals ); public static void init() { int packetId = 0; // Register the mount synchronization packet CHANNEL.registerMessage( packetId++, MountSyncPacket.class, MountSyncPacket::encode, MountSyncPacket::decode, (msg, context) -> msg.handle(context.get()) // Get the context with context.get() ); } }  
    • Do you use features of inventory profiles next (ipnext) or is there a change without it?
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.