Jump to content

[1.10.2] Custom slab issues


Erfurt

Recommended Posts

Hey guys,

 

So I have some small problems with my custom slabs, the first problem is that my double slab doesn't drop it's single slab counterpart, don't know how to fix that. The second problem is that the blockstate .json files seems to need some funky variants, and I'm not sure why that is. It's not something I think is really important to fix, as they work fine texture-wise, but it would be lovely if someone could see why, and maybe help me change it so that it would be more like the vanilla .json files.

 

Here's my Slab class

 

 

public abstract class EadoreSlab extends BlockSlab
{
private static final PropertyBool VARIANT = PropertyBool.create("variant");

public EadoreSlab(Material mat, String name)
{
	super(mat);
	this.setUnlocalizedName(name);
	this.setRegistryName(name);
	this.useNeighborBrightness = !this.isDouble(); 
	setHardness(2);
	if(mat == Material.WOOD)
	{
		Blocks.FIRE.setFireInfo(this, 5, 5);
	}

	if (!this.isDouble())
	{
            setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
        }

	IBlockState blockState = this.blockState.getBaseState();
        blockState = blockState.withProperty(VARIANT, false);
        if (!this.isDouble())
        {
            blockState.withProperty(HALF, EnumBlockHalf.BOTTOM);
        }
        
        setDefaultState(blockState);
}

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

@Override
public Comparable<?> getTypeForItem(ItemStack stack)
{
	return false;
}

@Override
public IProperty<?> getVariantProperty()
{
	return VARIANT;
}

@Override
public int damageDropped(IBlockState state)
{
	return 0;
}

@Override
public final IBlockState getStateFromMeta(final int meta) {
	IBlockState blockState = this.getDefaultState();
        blockState = blockState.withProperty(VARIANT, false);
        if (!this.isDouble()) {
            EnumBlockHalf value = EnumBlockHalf.BOTTOM;
            if ((meta &  != 0) {
                value = EnumBlockHalf.TOP;
            }

            blockState = blockState.withProperty(HALF, value);
        }

	return blockState;
}

@Override
public final int getMetaFromState(final IBlockState state) {
        if (this.isDouble()) {
           return 0;
        }

        if ((EnumBlockHalf) state.getValue(HALF) == EnumBlockHalf.TOP) {
            return 8;
        } else {
            return 0;
        }
}

@Override
protected final BlockStateContainer createBlockState() {
        if (this.isDouble()) {
            return new BlockStateContainer(this, new IProperty[] {VARIANT});
        } else {
            return new BlockStateContainer(this, new IProperty[] {VARIANT, HALF});
        }
}
}

 

 

 

Here's my Single/Double slab class

 

 

public class EadoreHalfSlab extends EadoreSlab
{

public EadoreHalfSlab(Material mat, String name)
{
	super(mat, name);
}

@Override
public boolean isDouble()
{
	//Double slab class returns true
	return false;
}

}

 

 

 

Here's the ItemSlab class

 

 

package erfurt.eadore.items;

import erfurt.eadore.blocks.EadoreDoubleSlab;
import erfurt.eadore.blocks.EadoreHalfSlab;
import net.minecraft.block.Block;
import net.minecraft.item.ItemSlab;

public class EadoreItemSlab extends ItemSlab
{

public EadoreItemSlab(Block block, EadoreHalfSlab singleSlab, EadoreDoubleSlab doubleSlab, Boolean stacked)
{
	super(block, singleSlab, doubleSlab);
}

}

 

 

 

Here's how I register my slab

 

 

public class BlockRegistry
{
public static Block planks_maple;

public static Block slab_half_maple;
public static Block slab_double_maple;


public static void init()
{
	planks_maple = new EadorePlanks("planks_maple");

	slab_half_maple = new EadoreHalfSlab(Material.WOOD, "slab_half_maple");
	slab_double_maple = new EadoreDoubleSlab(Material.WOOD, "slab_double_maple");
}

public static void register()
{
	registerBlock(planks_maple);

	registerSlab(slab_half_maple, slab_half_maple, slab_double_maple, false);
	registerSlab(slab_double_maple, slab_half_maple, slab_double_maple, false);
}

public static void registerRenders()
{
	registerRender(planks_maple);

	registerRender(slab_half_maple);
	registerRender(slab_double_maple);
}

public static void registerBlock(Block block)
{
	GameRegistry.register(block);
	GameRegistry.register(new ItemBlock(block).setRegistryName(block.getRegistryName()));
}

public static void registerSlab(Block block, Block singleSlab, Block doubleSlab, Boolean stacked)
{
	GameRegistry.register(block);
	GameRegistry.register(new EadoreItemSlab(block, (EadoreHalfSlab)singleSlab, (EadoreDoubleSlab)doubleSlab, stacked).setRegistryName(block.getRegistryName()));
}

public static void registerRender(Block block)
{
	Item item = Item.getItemFromBlock(block);
	ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(block.getRegistryName(), "normal"));
}
}

 

 

 

Here's the blockstate .json files.

 

 

slab_half_maple

{
    "variants": {
        "half=bottom,variant=false": { "model": "em:slab_half_maple" },
        "half=top,variant=false": { "model": "em:slab_upper_maple" },
        "half=bottom,variant=true": { "model": "em:slab_half_maple" },
        "half=top,variant=true": { "model": "em:slab_upper_maple" }
    }
}

slab_double_maple

{
    "variants": {
        "variant=false": { "model": "em:planks_maple" }
    }
}

 

 

Link to comment
Share on other sites

Override

getItem

to return the

ItemStack

dropped.

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

Link to comment
Share on other sites

If is a generic object I recommend doing a

 

return Item.itemFromBlock(this)

 

this will return the current item from the current block.

Disclaimer:  I been told to keep my opinions to myself, to shut up and that I am spreading lies and misinformation or even that my methods are unorthodox and or too irregular. Here are my suggestions take it or leave it.

Link to comment
Share on other sites

If is a generic object I recommend doing a

 

return Item.itemFromBlock(this)

 

this will return the current item from the current block.

 

Just to clarify, are you talking about using the getItem method in my ItemSlab class aswell, or something else?

Link to comment
Share on other sites

getItem in your custom slab

 

have a look at planks . they use VARIANTS and sub blocks.

 

 

To drop the correct sub-block variant you need to override a bunch of functions

 

getItem

 

getSubBlock

 

getDamagedDropped (or something similar)

 

 

Which is why I NEVER EVER EVER use sub block variants for wood, slabs, planks and the like unless I 100000% need it. Is stupidly complicated. You can just create each individual block separately register each model and simply return itself  done.  You can even use Block to do it don't even need a custom block.

 

Not saying you should do it like me just that I think you will reduce 1 year of your life figuring out the sub block meta bugs and issues.

Disclaimer:  I been told to keep my opinions to myself, to shut up and that I am spreading lies and misinformation or even that my methods are unorthodox and or too irregular. Here are my suggestions take it or leave it.

Link to comment
Share on other sites

getItem in your custom slab

 

have a look at planks . they use VARIANTS and sub blocks.

 

 

To drop the correct sub-block variant you need to override a bunch of functions

 

getItem

 

getSubBlock

 

getDamagedDropped (or something similar)

 

 

Which is why I NEVER EVER EVER use sub block variants for wood, slabs, planks and the like unless I 100000% need it. Is stupidly complicated. You can just create each individual block separately register each model and simply return itself  done.  You can even use Block to do it don't even need a custom block.

 

Not saying you should do it like me just that I think you will reduce 1 year of your life figuring out the sub block meta bugs and issues.

 

I hate using subblocks aswell, can never get it to work :)

But with slabs, you kinda have to, at least to some degree, as far as I know, but I could be wrong.

 

However I think I understand what you want me to do, it's just that I can't seem to get it to work without making them fully subblocks, with an EnumType method and all that. Properly going to take me forever to get this to work, unless there is an easier way, that I just can't see...

 

I believe that this is what you mean, example taking from BlockStoneSlab

 

 

@Nullable
    public Item getItemDropped(IBlockState state, Random rand, int fortune)
    {
        return Item.getItemFromBlock(Blocks.STONE_SLAB);
    }

    public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
    {
        return new ItemStack(Blocks.STONE_SLAB, 1, ((BlockStoneSlab.EnumType)state.getValue(VARIANT)).getMetadata());
    }
public int damageDropped(IBlockState state)
    {
        return ((BlockStoneSlab.EnumType)state.getValue(VARIANT)).getMetadata();
    }

 

 

 

What I can't seem to get around is BlockStoneSlab.EnumType, which would imply that I need to make a custom EnumType in my Slab class.

 

EDIT: I have tried to replace BlockStoneSlab.EnumType with 0, as that seemed to be  the way to do it, didn't work. Thought I had it then, but I did not :/

Link to comment
Share on other sites

You can make custom enums or custom properties but you need to define them in a separate class.  I can't remember now right now but is online somewhere. Is pretty simple.

 

I know watchu mean that you need to use sub blocks but I think you can get away by doing blockstate logic + bounding box tricks.

 

I'm actualy gonna make my own custom slab and stairs soon so I'll let you know when I succceed.

Disclaimer:  I been told to keep my opinions to myself, to shut up and that I am spreading lies and misinformation or even that my methods are unorthodox and or too irregular. Here are my suggestions take it or leave it.

Link to comment
Share on other sites

You can make custom enums or custom properties but you need to define them in a separate class.  I can't remember now right now but is online somewhere. Is pretty simple.

 

I know watchu mean that you need to use sub blocks but I think you can get away by doing blockstate logic + bounding box tricks.

 

I'm actualy gonna make my own custom slab and stairs soon so I'll let you know when I succceed.

 

Cool, when/if I get mine to work, I'll let you know aswell

Link to comment
Share on other sites

Erfurt I noticed there's a glitch with stairs being too dark when Smooth Lighting is OFF possibly with slabs too? 

 

Placing this.setLightOpacity(0); in the constructor fixes the issue.

 

Also I have successfully created custom stairs . Slabs next in a lil bit.

Disclaimer:  I been told to keep my opinions to myself, to shut up and that I am spreading lies and misinformation or even that my methods are unorthodox and or too irregular. Here are my suggestions take it or leave it.

Link to comment
Share on other sites

Erfurt I noticed there's a glitch with stairs being too dark when Smooth Lighting is OFF possibly with slabs too? 

 

Placing this.setLightOpacity(0); in the constructor fixes the issue.

 

Also I have successfully created custom stairs . Slabs next in a lil bit.

 

Cool mate, I haven't seen any light issues with my slabs tho :)

Link to comment
Share on other sites

Erfurt I noticed there's a glitch with stairs being too dark when Smooth Lighting is OFF possibly with slabs too? 

 

Placing this.setLightOpacity(0); in the constructor fixes the issue.

 

Also I have successfully created custom stairs . Slabs next in a lil bit.

 

setLightOpacity is not what you want, as it is meant how much light you want to let pass through the block.

0 means you let all the light get through. Try it out in the dark place a glowstone block for example on the ground and surround it with your slabs in such a way the glowstone is not visible anymore. You will see light passing through.

 

The darkness *glitch* you see, can be fixed with this:

useNeighborBrightness = true;

In this way the block will use the lightvalue of the block(s) next to it , whatever position that is (left, right, in front, up, etc etc)

 

So when do you use setLightOpacity? For example glass blocks or in your case maybe glass slabs or glass stairs or what ever block that is transparent.

Link to comment
Share on other sites

I also think you do not need itemslab. I have also fully functional slabs.

I have 3 classes for it:

 

- a class that extends BlockSlab (CustomBlockSlab for example)

- a class for halfslabs that extends CustomBlockSlab (CustomHalfSlab)

- a class for doubleslabs that extends CustomBlockSlab (CustomDoubleSlab)

 

the only difference half and double have is this:

@Override
public boolean isDouble() {
	// TODO Auto-generated method stub
	return true;
}

the half has it set to false and the double to true

 

I tried before the pass this boolean variable directly as an argument to CustomBlockSlab, because in this way i would only need 1 file. For some reason this doesn't work and i do not know why. So i used 3 files for each set of slabs.

 

You can define up to 8 different types in your slabs

I'll give you an example of my slabs.

 

BlockChalkstoneBlockSlab.class:

 

public abstract class BlockChalkstoneBlockSlab extends BlockSlab implements IMetaBlockName{

//private static final PropertyBool VARIANT = PropertyBool.create("variant");
public static final PropertyEnum TYPE = PropertyEnum.create("type", BlockChalkstoneBlockSlab.EnumType.class);

public BlockChalkstoneBlockSlab(String unlocalname, String registryname) {
	super(Material.ROCK);
	setUnlocalizedName(unlocalname);
	setRegistryName(registryname);
	useNeighborBrightness = true;
	setHardness(0.8F);
        setResistance(5.0F);
        setSoundType(SoundType.STONE);
        setCreativeTab(Tem.slabstab);
	IBlockState state = this.blockState.getBaseState();
	//state.withProperty(VARIANT, false);
	state.withProperty(TYPE, EnumType.RAW);
	if(!this.isDouble()){
		state.withProperty(HALF, EnumBlockHalf.BOTTOM);
	}
	setDefaultState(state);
	// TODO Auto-generated constructor stub
}


@Override
public String getUnlocalizedName(int meta){
	return this.getUnlocalizedName() + "_" + EnumType.values()[meta];
}
@Override
public Comparable<?> getTypeForItem(ItemStack stack) {
	// TODO Auto-generated method stub
	return BlockChalkstoneBlockSlab.EnumType.byMetadata(stack.getMetadata() & 7);
}
@Override
public IProperty<?> getVariantProperty(){
	return TYPE;
}
@Override
public Item getItemDropped(IBlockState state, Random rand, int fortune)
    {
        return Item.getItemFromBlock(ModBlocks.chalkstoneslab);
    }
@Override
public int quantityDropped(Random random)
    {
        return this.isDouble() ? 2 : 1;
    }

@Override
public int damageDropped (IBlockState state){
	return ((BlockBrickedClayBlockSlab1.EnumType) state.getValue(TYPE)).getID();

}

@Override
public final IBlockState getStateFromMeta (int meta){
	IBlockState blockstate = this.getDefaultState();
	blockstate = blockstate.withProperty(TYPE,BlockChalkstoneBlockSlab.EnumType.byMetadata(meta & 7));
	if(!this.isDouble()){
		blockstate = blockstate.withProperty(HALF, (meta & 8 ) == 8 ? EnumBlockHalf.BOTTOM : EnumBlockHalf.TOP);
		}
	return blockstate;
}

@Override
public final int getMetaFromState(IBlockState state){
	int meta = ((BlockChalkstoneBlockSlab.EnumType) state.getValue(TYPE)).getID();
	if (!this.isDouble() && state.getValue(HALF) == EnumBlockHalf.TOP){
		meta |=8;
	}
	return meta;
}
@Override
protected final BlockStateContainer createBlockState(){
	if (this.isDouble()){
		return new BlockStateContainer(this, getVariantProperty());
	}
	else {
		return new BlockStateContainer(this, getVariantProperty(), HALF);
	}
}

@Override
public void getSubBlocks(Item itemIn, CreativeTabs tab, List list) {
	for (EnumType t : EnumType.values())
    list.add(new ItemStack(itemIn, 1, t.ordinal()));  
}

@Override
public String getSpecialName(ItemStack stack) {
	return EnumType.values()[stack.getItemDamage()].name().toLowerCase();
}

public enum EnumType implements IStringSerializable{

	RAW(0, "raw"), SMOOTH(1, "smooth"), BRICKED(2, "bricked");
	private static final BlockChalkstoneBlockSlab.EnumType[] META_LOOKUP = new BlockChalkstoneBlockSlab.EnumType[values().length];

    private int ID;
    private String name;
   
    private EnumType(int ID, String name) {
        this.ID = ID;
        this.name = name;
            
    }
    @Override
    public String getName() {
        return name;
    }
    public int getID() {
        return ID;
    }
    @Override
    public String toString() {
        return getName();
    }
    public static BlockChalkstoneBlockSlab.EnumType byMetadata(int meta)
        {
            if (meta < 0 || meta >= META_LOOKUP.length)
            {
                meta = 0;
            }

            return META_LOOKUP[meta];
        }
    static
        {
            for (BlockChalkstoneBlockSlab.EnumType types : values())
            {
                META_LOOKUP[types.getID()] = types;
            }
        }
}

}

 

 

BlockChalkstoneHalfSlab.class:

 

public class BlockChalkstoneHalfSlab extends BlockChalkstoneBlockSlab{

//public boolean isStacked;
public BlockChalkstoneHalfSlab(String unlocalname, String registryname) {
	super(unlocalname, registryname);
	//isStacked = stacked;
	// TODO Auto-generated constructor stub
}

@Override
public boolean isDouble() {
	// TODO Auto-generated method stub
	return false;
}


}

 

 

BlockChalkstoneDoubleSlab.class:

 

public class BlockChalkstoneDoubleSlab extends BlockChalkstoneBlockSlab{

public BlockChalkstoneDoubleSlab(String unlocalname, String registryname) {
	super(unlocalname, registryname);
	// TODO Auto-generated constructor stub
}

@Override
public boolean isDouble() {
	// TODO Auto-generated method stub
	return true;
}
}

 

 

i create it like this:

chalkstoneslab = new BlockChalkstoneHalfSlab(References.temBlocks.CHALKSTONEHALFSLAB.getUnlocalizedName(), References.temBlocks.CHALKSTONEHALFSLAB.getRegistryName());
	chalkstonedoubleslab = new BlockChalkstoneDoubleSlab(References.temBlocks.CHALKSTONEDOUBLESLAB.getUnlocalizedName(), References.temBlocks.CHALKSTONEDOUBLESLAB.getRegistryName());

 

register it like this:

registerBlockSlab(chalkstoneslab, chalkstonedoubleslab);

I have created a special method to register it

it looks like this:

private static void registerBlockSlab(Block slab, Block doubleslab){
	GameRegistry.register(slab);
	GameRegistry.register(doubleslab);
	ItemSlab item = new ItemSlab(slab, (BlockSlab) slab, (BlockSlab) doubleslab);
	item.setRegistryName(slab.getRegistryName());
	GameRegistry.register(item);
}

 

Now try not to copy paste this all. Try to understand how it works.

The way i did it is maybe not the best way at all. I'm not an expert at all, but maybe i can help you!

As far i know it all works fine for me.

You can figure out by yourself how the rendering works. If not we will hear from you soon.

Link to comment
Share on other sites

You can figure out by yourself how the rendering works. If not we will hear from you soon.

 

For the rendering I believe that I have to use this method

public static void registerRender(Block block)
{
	Item item = Item.getItemFromBlock(block);
	ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(block.getRegistryName(), "normal"));
}

 

For both singleSlab and doubleSlab, if I'm wrong please do correct me :)

Link to comment
Share on other sites

You can also make multiple types of the same method like this:

 

private static void registerRender(Block block, int meta, String variant){
	ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), meta, new ModelResourceLocation(block.getRegistryName(),variant));	
}
private static void registerRender(Block block, String variant){
	ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), 0, new ModelResourceLocation(block.getRegistryName(),variant));
	}
private static void registerRender(Block block){
	ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), 0, new ModelResourceLocation(block.getRegistryName(),"inventory"));
	}

Because this method is used for the same purpose you can keep the same naming for it. That way you don't need to invent multiple names for multiple tasks that slightly differs.

Sometimes you only want to pass a block, sometimes you want meta, sometimes you want to define an exact variant.

 

You only register the render for your halfslab. You still need the blockstate for both.

Link to comment
Share on other sites

Or like how I have things:

https://github.com/Draco18s/ReasonableRealism/blob/master/src/main/java/com/draco18s/hardlib/EasyRegistry.java

https://github.com/Draco18s/ReasonableRealism/blob/master/src/main/java/com/draco18s/hardlib/client/ClientEasyRegistry.java

 

(Those classes are proxys for a library mod).  I give the methods different names so that I know what's going to happen.  It's a verification that I'm typing out the method that does what I'm thinking I want to happen.  But yes, they could be renamed to all have the same name and just be overloaded.

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.

Link to comment
Share on other sites

I'm working on the slab right now . Works until I place it then it crashes saying there's no property "half" 

Disclaimer:  I been told to keep my opinions to myself, to shut up and that I am spreading lies and misinformation or even that my methods are unorthodox and or too irregular. Here are my suggestions take it or leave it.

Link to comment
Share on other sites

Your block class doesn't have a property "half" for some reason.

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.

Link to comment
Share on other sites

I managed to make it working by adding the meta and createBlockstate but now it crashes because 

 

Comparable<?> comparable1 = iblockstate.getValue(iproperty);

 

my comparable returns null because I have no VARIANT.

 

I tried to create my own SlabItem but  I'm kinda confused as this complicated stupid MC way of doing things with sub blocks and meta.

Disclaimer:  I been told to keep my opinions to myself, to shut up and that I am spreading lies and misinformation or even that my methods are unorthodox and or too irregular. Here are my suggestions take it or leave it.

Link to comment
Share on other sites

Hey I managed to figure this out. 100% working slabs.

 

Unlike the answer above I actually use a custom ItemSlab  which gets rid of VARIANT bs.

 

Here is my custom SlabBlock  (generic slab block you can use for any slab block base)

 

package com.technorcery.common.blocks;

import com.technorcery.common.ModData;

import net.minecraft.block.BlockSlab;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;

public class SlabBlock extends BlockSlab{

public SlabBlock(String name, Material materialIn) {
	super(materialIn);
	this.setUnlocalizedName(name);
	this.setRegistryName(name);
	this.setCreativeTab(ModData.CREATIVE_TAB);
	this.useNeighborBrightness = true;
}

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

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

@Override
public IProperty<?> getVariantProperty() {
        return null;
}

@Override
public Comparable<?> getTypeForItem(ItemStack stack) {
	return null;
}

@Override
    public IBlockState getStateFromMeta(int meta)
    {
        IBlockState iblockstate = this.getDefaultState();

        if (!this.isDouble())
        {
            iblockstate = iblockstate.withProperty(HALF, (meta &  == 0 ? BlockSlab.EnumBlockHalf.BOTTOM : BlockSlab.EnumBlockHalf.TOP);
        }

        return iblockstate;
    }

    @Override
    public int getMetaFromState(IBlockState state)
    {
        int i = 0;

        if (!this.isDouble() && state.getValue(HALF) == BlockSlab.EnumBlockHalf.TOP)
        {
            i |= 8;
        }

        return i;
    }
    
    @Override
    protected BlockStateContainer createBlockState()
    {
        return this.isDouble() ? new BlockStateContainer(this): new BlockStateContainer(this, new IProperty[] {HALF});
    }
}

 

 

 

Here is my half slab for WOOD only . This is what I actually use to create the block and half slab (continue reading)

 

package com.technorcery.common.blocks;

import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;

public class HalfSlabWoodBlock extends SlabBlock {

public HalfSlabWoodBlock(String name) {
	super(name, Material.WOOD);
	this.setSoundType(SoundType.WOOD);
	this.setHardness(2.0F);
	this.setResistance(5.0F);
}
}

 

 

This is my double slab (as you can see this returns isDouble true..by default my custom base slab is set to double false which is why in the half slab I don't set this at all)

 

package com.technorcery.common.blocks;

import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;

public class DoubleSlabWoodBlock extends SlabBlock {

public DoubleSlabWoodBlock(String name) {
	super(name, Material.WOOD);
	this.setSoundType(SoundType.WOOD);
	this.setHardness(2.0F);
	this.setResistance(5.0F);
	this.setDefaultState(this.getDefaultState());
}

    public boolean isDouble()
    {
        return true;
    }

}

 

 

 

Here is my custom ItemSlab (the trick here is I got rid of Comparator<?> and IProperty because that was used for VARIANT. in other words this type of slab is defined one at a time and does not have subtypes or sub blocks or variants)

 

package com.technorcery.common.items;

import net.minecraft.block.Block;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.SoundType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

public class SlabItem extends ItemBlock
{
    private final BlockSlab singleSlab;
    private final BlockSlab doubleSlab;

    public SlabItem(Block block, BlockSlab singleSlab, BlockSlab doubleSlab)
    {
        super(block);
        this.singleSlab = singleSlab;
        this.doubleSlab = doubleSlab;
        this.setMaxDamage(0);
        this.setHasSubtypes(true);
    }

    @Override
    public int getMetadata(int damage)
    {
       return 0;
    }

    @Override
    public String getUnlocalizedName(ItemStack stack)
    {
       return this.singleSlab.getUnlocalizedName();
    }

    public EnumActionResult onItemUse(ItemStack stack, EntityPlayer playerIn, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
    {
        if (stack.stackSize != 0 && playerIn.canPlayerEdit(pos.offset(facing), facing, stack))
        {
            Comparable<?> comparable = this.singleSlab.getTypeForItem(stack);
            IBlockState iblockstate = worldIn.getBlockState(pos);

            if (iblockstate.getBlock() == this.singleSlab)
            {
                BlockSlab.EnumBlockHalf blockslab$enumblockhalf = (BlockSlab.EnumBlockHalf)iblockstate.getValue(BlockSlab.HALF);

                if ((facing == EnumFacing.UP && blockslab$enumblockhalf == BlockSlab.EnumBlockHalf.BOTTOM || facing == EnumFacing.DOWN && blockslab$enumblockhalf == BlockSlab.EnumBlockHalf.TOP))
                {
                    IBlockState iblockstate1 = this.doubleSlab.getDefaultState();
                    AxisAlignedBB axisalignedbb = iblockstate1.getCollisionBoundingBox(worldIn, pos);

                    if (axisalignedbb != Block.NULL_AABB && worldIn.checkNoEntityCollision(axisalignedbb.offset(pos)) && worldIn.setBlockState(pos, iblockstate1, 11))
                    {
                        SoundType soundtype = this.doubleSlab.getSoundType(iblockstate1, worldIn, pos,playerIn);
                        worldIn.playSound(playerIn, pos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
                        --stack.stackSize;
                    }

                    return EnumActionResult.SUCCESS;
                }
            }

            return this.tryPlace(playerIn, stack, worldIn, pos.offset(facing), comparable) ? EnumActionResult.SUCCESS : super.onItemUse(stack, playerIn, worldIn, pos, hand, facing, hitX, hitY, hitZ);
        }
        else
        {
            return EnumActionResult.FAIL;
        }
    }
   

    @SideOnly(Side.CLIENT)
    public boolean canPlaceBlockOnSide(World worldIn, BlockPos pos, EnumFacing side, EntityPlayer player, ItemStack stack)
    {
        BlockPos blockpos = pos;
        IBlockState iblockstate = worldIn.getBlockState(pos);

        if (iblockstate.getBlock() == this.singleSlab)
        {
            boolean flag = iblockstate.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.TOP;

            if ((side == EnumFacing.UP && !flag || side == EnumFacing.DOWN && flag))
            {
                return true;
            }
        }

        pos = pos.offset(side);
        IBlockState iblockstate1 = worldIn.getBlockState(pos);
        return iblockstate1.getBlock() == this.singleSlab ? true : super.canPlaceBlockOnSide(worldIn, blockpos, side, player, stack);
    } 

    private boolean tryPlace(EntityPlayer player, ItemStack stack, World worldIn, BlockPos pos, Object itemSlabType)
    {
        IBlockState iblockstate = worldIn.getBlockState(pos);

        if (iblockstate.getBlock() == this.singleSlab)
        {
            Comparable<?> comparable = iblockstate.getValue(this.singleSlab.getVariantProperty());

            if (comparable == itemSlabType)
            {
                IBlockState iblockstate1 = this.doubleSlab.getDefaultState();
                AxisAlignedBB axisalignedbb = iblockstate1.getCollisionBoundingBox(worldIn, pos);

                if (axisalignedbb != Block.NULL_AABB && worldIn.checkNoEntityCollision(axisalignedbb.offset(pos)) && worldIn.setBlockState(pos, iblockstate1, 11))
                {
                    SoundType soundtype = this.doubleSlab.getSoundType(iblockstate1, worldIn, pos, player);
                    worldIn.playSound(player, pos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
                    --stack.stackSize;
                }

                return true;
            }
        }

        return false;
    }
}

 

 

 

This is how I register the item

		public static final ItemBlock SLAB_APPLE = (ItemBlock) new SlabItem(ModBlocks.HALFSLAB_APPLE, (BlockSlab) ModBlocks.HALFSLAB_APPLE, (BlockSlab) ModBlocks.DOUBLESLAB_APPLE).setUnlocalizedName("slabApple").setRegistryName("slabApple").setCreativeTab(ModData.CREATIVE_TAB);

 

The trick is

Blockitem mySlab = new SlabItem( halfSlab, halfSlab, fullSlab)

 

 

This is how I register the block

		public static final Block DOUBLESLAB_APPLE = (new DoubleSlabWoodBlock("doubleSlabApple"));
	public static final Block HALFSLAB_APPLE = (new HalfSlabWoodBlock("halfSlabApple"));	

 

For the json you make your slab item parent to you halfSlab model and your blockstate would be same as regular MC slab . 2 blockstates halfSlab and fulLSlab . halfSlab has 2 HALF properties BOTTOM when to place it lower and UPPER when you place it higher . The BOTTOM model is your normal slab that you also use for item parent.

 

Disclaimer:  I been told to keep my opinions to myself, to shut up and that I am spreading lies and misinformation or even that my methods are unorthodox and or too irregular. Here are my suggestions take it or leave it.

Link to comment
Share on other sites

Here is the link to my project

https://github.com/trollworkout/technorcery/tree/master/src/main/java/com/technorcery

 

knock yourself out

 

Note that the way my project is structured is like this

blocks = unique blocks that need special classes

client = anything that runs on client side

common = anything that runs on both client and server

common/block = generic blocks (here you gonna find the slab, stairs, halfslab..)

common/item = generic item (here you gonna find the custom itemslab)

entity = entities

sever = anything that runs on server

 

 

Disclaimer:  I been told to keep my opinions to myself, to shut up and that I am spreading lies and misinformation or even that my methods are unorthodox and or too irregular. Here are my suggestions take it or leave it.

Link to comment
Share on other sites

Your block class doesn't have a property "half" for some reason.

 

I was missing the getStateFromMeta getMetaFromState and createBlockstate functions so it didn't understand what half=bottom half=upper were

Disclaimer:  I been told to keep my opinions to myself, to shut up and that I am spreading lies and misinformation or even that my methods are unorthodox and or too irregular. Here are my suggestions take it or leave it.

Link to comment
Share on other sites

Hey I managed to figure this out. 100% working slabs

 

Unlike the answer above I actually use a custom ItemSlab  which gets rid of VARIANT bs.

 

I also gave a 100% working slabs example!

There is no need to use ItemSlab and those VARIANTS are no "bs".

Stop giving people bad advice and please stop being stubborn.

Link to comment
Share on other sites

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

    • I created my own modpack just for mainly entities right now and im having issues with only a handful of the mobs. is there a way someone could help go over my work and check whats wrong? its a file 
    • Hi, I have a problem with my minecraft: I'm in forge 1.20.1 and I have several mods installed, (link to photo below) and after a while, at random, the game freezes, I can't play or move but I can still hear the game in the background, there's just the image that remains, (problematic when I fight a fire dragon :() ) can you help me? my mods:   zmedievalmusic-1.20.1-2.1 treeharvester-1.20.1-8.7 tctcore-1.0-1.20.1 specialmobs-1.20.1-3.1.3 simpleOres2-1.20.1-6.0.0.2 OldCombatMod_1.20x.jar oculus-mc1.20.1-1.7.0 medieval_buildings-forge-1.0.2 matmos-5.2-forge-1.20.1 journeymap-1.20.1-5.9.18-forge jei-1.20.1-forge-15.8.0.11 iceandfire-2.1.13-1.20.1-beta-4 healthindicatortxf-1.20.1-1.2.2-forge geckolib-forge-1.20.1-4.4.7 embeddium-0.3.25+mc1.20.1 dynamiclights-1.20.1-1.2 cupboard-1.20.1-2.7 crust-1.20.1-2.3.3 collective-1.20.1-7.71 citadel-2.4.9-1.20.1 bucketlib-1.20.1-2.3.0.5 born_in_chaos_(Forge)1.20.1_1.3.1 betterfpsdist-4.4   forge 1.20.1 (47.3.5) i fink it's because of ice and fire mod, but i want it thank to help me! i hope you are well Translated with DeepL.com (free version)
    • Long story short, my girlfriend found a mod for Minecraft she wanted but it was for Pocket Edition. So I took it on myself to try and port it over and it has gone fairly well until the point I had to work with particles. Basically, I had it working using animateTick but I was checking if the block name contained a certain value to specify the lantern's color and as such choose which particle to spawn. I was initially trying to do this via the constructor, but this value hasn't been initialized that early and I can't seem to find some event or method to override which ideally happens when the block is loaded/placed. Performing upwards to 16 string comparisons per tick isn't exactly efficient so I want to try and optimize this. By the time animateTick starts executing, the name is properly initialized and I can use that to set my property accordingly. But this is where I'm starting to run into a weird issue. This is my current code; public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource randomSource) { // It's not fully initialized yet... I guess? if (this.getName().toString().contains("air")) return; if (!state.getValue(COLOR_SET)) { // This method doesn't work at all, neither states are updated var blockState = level.getBlockState(pos); blockState.setValue(LANTERNCOLOR, this.getBlockColor()); blockState.setValue(COLOR_SET, true); level.setBlockAndUpdate(pos, blockState); } double d0 = (double)pos.getX() + randomSource.nextDouble(); double d1 = (double)pos.getY() + randomSource.nextDouble(); double d2 = (double)pos.getZ() + randomSource.nextDouble(); // No idea how to better do this without adding 5 000 new files if (level.getBlockState(pos).getValue(LANTERNCOLOR) == DyeColor.WHITE.getId()) level.addParticle(PaperLanterns.LANTERN_GLOW_WHITE.get(), d0, d1, d2, 0.0D, ThreadLocalRandom.current().nextDouble(-0.10D, 0.0D), 0.0D); if (level.getBlockState(pos).getValue(LANTERNCOLOR) == DyeColor.BLUE.getId()) level.addParticle(PaperLanterns.LANTERN_GLOW_BLUE.get(), d0, d1, d2, 0.0D, ThreadLocalRandom.current().nextDouble(-0.10D, 0.0D), 0.0D); } COLOR_SET is a BooleanProperty meant to ensure this is only executed once, for performance reasons. LANTERNCOLOR is currently an IntegerProperty (it used to be an EnumProperty, but been changing stuff around trying to fix the issue) which specified the color. My issue is that I can only set one of these states, for example like this; if (!state.getValue(COLOR_SET)) { // LANTERNCOLOR is set successfully, but not COLORSET level.setBlockAndUpdate(pos, state.setValue(LANTERNCOLOR, this.getBlockColor())); level.setBlockAndUpdate(pos, state.setValue(COLOR_SET, true)); } // OR if (!state.getValue(COLOR_SET)) { // COLOR_SET is set successfully, but not LANTERNCOLOR level.setBlockAndUpdate(pos, state.setValue(COLOR_SET, true)); level.setBlockAndUpdate(pos, state.setValue(LANTERNCOLOR, this.getBlockColor())); } So I can only seemingly set one state at a time, I now know that my issue wasn't in my usage of EnumProperty so once I solve this I will be going back to that and using a switch-case. But I would love some pointers as to why I can only set one of these states. Is it because once you set it and update it, that instance of the block is now considered dirty and as such accepts no more state changes or something? I know the code's a bit all over the place with how I retrieve the states. I'm still learning and have been testing a bunch trying to get this to work, but have now found the issue but no idea how to solve it 😅 If there's a better way of setting this LANTERNCOLOR property and ensuring it's only executed once, that would be even better. The sole purpose of this is to choose which particle to spawn, since the particle colors are hardcoded.
    • Hi, I have a problem with my minecraft: I'm in forge 1.20.1 and I have several mods installed, (link to photo below) and after a while, at random, the game freezes, I can't play or move but I can still hear the game in the background, there's just the image that remains, (problematic when I fight a fire dragon :() ) can you help me? my mods: file:///C:/Users/meria/Pictures/Capture.PNG forge 1.20.1 (47.3.5) i fink it's because of ice and fire mod, but i want it thank to help me! i hope you are well Translated with DeepL.com (free version)
  • Topics

×
×
  • Create New...

Important Information

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