Пропадает блок при объединении двух BlockSlab

Версия Minecraft
1.12.2
25
6
Всем привет!
Продолжаю переписывать мод MoreMaterials под 1.12.2. Добрался теперь до создания своих кастомных плит, то есть BlockSlab.
Отдельные плиты получилось сделать:

2020-01-29_10.57.07.png

А вот когда соединяешь две такие одинаковые плиты вместе то получается такая ерунда:

2020-01-29_10.57.12.png

Когда перезаходишь на сервер, этот блок исчезает. Если пытаешься его сломать - он исчезает без звука и дропа.
Сколько вот не смотрю разных примеров не могу понять в чём проблема. Ошибок в логах не обнаружил...
Помогите, пожалуйста, кто сталкивался с такой же проблемой и/или знает, как её исправить
BlocksRegister.class:
package de.shittyco.morematerials.blocks;

import de.shittyco.morematerials.blocks.fence.BlockBrickFence;
import de.shittyco.morematerials.blocks.fence.BlockBrickFenceGate;
import de.shittyco.morematerials.blocks.slab.BlockDoubleStainedBrickSlab;
import de.shittyco.morematerials.blocks.slab.BlockHalfStainedBrickSlab;
import de.shittyco.morematerials.blocks.slab.BlockStainedBrickSlab;
import de.shittyco.morematerials.blocks.wall.BlockStainedBrickWall;
import de.shittyco.morematerials.utils.ColorUtility;
import de.shittyco.morematerials.utils.WoodUtility;
import net.minecraft.block.Block;
import net.minecraft.block.BlockSlab;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.ModelBakery;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemSlab;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

public class BlocksRegister {
    public static Block stainedBrickBlocks = new BlockStainedBricks();

    public static Block woodenFrame = new BlockWoodenFrame();

    public static Block backslashWoodenFrame = new BlockBackslashWoodenFrame();

    public static Block crossWoodenFrame = new BlockCrossWoodenFrame();

    public static Block slashWoodenFrame = new BlockSlashWoodenFrame();

    public static Block brick_fence_black = new BlockBrickFence("brick_fence_black");
    public static Block brick_fence_gate_black = new BlockBrickFenceGate("brick_fence_gate_black");

    public static Block brick_fence_blue = new BlockBrickFence("brick_fence_blue");
    public static Block brick_fence_gate_blue = new BlockBrickFenceGate("brick_fence_gate_blue");

    public static Block brick_fence_brown = new BlockBrickFence("brick_fence_brown");
    public static Block brick_fence_gate_brown = new BlockBrickFenceGate("brick_fence_gate_brown");

    public static Block brick_fence_cyan = new BlockBrickFence("brick_fence_cyan");
    public static Block brick_fence_gate_cyan = new BlockBrickFenceGate("brick_fence_gate_cyan");

    public static Block brick_fence_gray = new BlockBrickFence("brick_fence_gray");
    public static Block brick_fence_gate_gray = new BlockBrickFenceGate("brick_fence_gate_gray");

    public static Block brick_fence_green = new BlockBrickFence("brick_fence_green");
    public static Block brick_fence_gate_green = new BlockBrickFenceGate("brick_fence_gate_green");

    public static Block brick_fence_light_blue = new BlockBrickFence("brick_fence_light_blue");
    public static Block brick_fence_gate_light_blue = new BlockBrickFenceGate("brick_fence_gate_light_blue");

    public static Block brick_fence_lime = new BlockBrickFence("brick_fence_lime");
    public static Block brick_fence_gate_lime = new BlockBrickFenceGate("brick_fence_gate_lime");

    public static Block brick_fence_magenta = new BlockBrickFence("brick_fence_magenta");
    public static Block brick_fence_gate_magenta = new BlockBrickFenceGate("brick_fence_gate_magenta");

    public static Block brick_fence_orange = new BlockBrickFence("brick_fence_orange");
    public static Block brick_fence_gate_orange = new BlockBrickFenceGate("brick_fence_gate_orange");

    public static Block brick_fence_pink = new BlockBrickFence("brick_fence_pink");
    public static Block brick_fence_gate_pink = new BlockBrickFenceGate("brick_fence_gate_pink");

    public static Block brick_fence_purple = new BlockBrickFence("brick_fence_purple");
    public static Block brick_fence_gate_purple = new BlockBrickFenceGate("brick_fence_gate_purple");

    public static Block brick_fence_red = new BlockBrickFence("brick_fence_red");
    public static Block brick_fence_gate_red = new BlockBrickFenceGate("brick_fence_gate_red");

    public static Block brick_fence_silver = new BlockBrickFence("brick_fence_silver");
    public static Block brick_fence_gate_silver = new BlockBrickFenceGate("brick_fence_gate_silver");

    public static Block brick_fence_white = new BlockBrickFence("brick_fence_white");
    public static Block brick_fence_gate_white = new BlockBrickFenceGate("brick_fence_gate_white");

    public static Block brick_fence_yellow = new BlockBrickFence("brick_fence_yellow");
    public static Block brick_fence_gate_yellow = new BlockBrickFenceGate("brick_fence_gate_yellow");

    public static Block[] stainedBrickWallBlocks = new BlockStainedBrickWall[ColorUtility.COLOR_COUNT];
    
    public static Block[] stainedBrickSlabBlocks = new BlockStainedBrickSlab[2 * ColorUtility.COLOR_COUNT];
    
    public static void register()
    {
        setRegister(stainedBrickBlocks, new ItemBlockStainedBricks(stainedBrickBlocks));
        setRegister(woodenFrame, new ItemBlockWoodenFrame(woodenFrame));
        setRegister(backslashWoodenFrame, new ItemBlockWoodenFrame(backslashWoodenFrame));
        setRegister(crossWoodenFrame, new ItemBlockWoodenFrame(crossWoodenFrame));
        setRegister(slashWoodenFrame, new ItemBlockWoodenFrame(slashWoodenFrame));

        for (int i = 0; i < ColorUtility.COLOR_COUNT; i++) {
            BlockStainedBrickWall wall = new BlockStainedBrickWall(stainedBrickBlocks, i);
            stainedBrickWallBlocks[i] = wall;
            setRegister(wall);
            
            BlockHalfStainedBrickSlab slab = new BlockHalfStainedBrickSlab(i);
            BlockDoubleStainedBrickSlab doubleSlab = new BlockDoubleStainedBrickSlab(i);
            stainedBrickSlabBlocks[2 * i] = slab;
            stainedBrickSlabBlocks[2 * i + 1] = doubleSlab;
            setRegister(slab, new ItemSlab(slab, slab, doubleSlab));
        }

    }

    @SideOnly(Side.CLIENT)
    public static void registerRender()
    {
        setRender(stainedBrickBlocks, ColorUtility.COLOR_COUNT, ColorUtility.COLOR_IDS);
        setRender(woodenFrame, WoodUtility.WOOD_TYPE_COUNT, WoodUtility.WOOD_TYPE_IDS);
        setRender(backslashWoodenFrame, WoodUtility.WOOD_TYPE_COUNT, WoodUtility.WOOD_TYPE_IDS);
        setRender(crossWoodenFrame, WoodUtility.WOOD_TYPE_COUNT, WoodUtility.WOOD_TYPE_IDS);
        setRender(slashWoodenFrame, WoodUtility.WOOD_TYPE_COUNT, WoodUtility.WOOD_TYPE_IDS);

        setRender(brick_fence_black);
        setRender(brick_fence_gate_black);

        setRender(brick_fence_blue);
        setRender(brick_fence_gate_blue);

        setRender(brick_fence_brown);
        setRender(brick_fence_gate_brown);

        setRender(brick_fence_cyan);
        setRender(brick_fence_gate_cyan);

        setRender(brick_fence_gray);
        setRender(brick_fence_gate_gray);

        setRender(brick_fence_green);
        setRender(brick_fence_gate_green);

        setRender(brick_fence_light_blue);
        setRender(brick_fence_gate_light_blue);

        setRender(brick_fence_lime);
        setRender(brick_fence_gate_lime);

        setRender(brick_fence_magenta);
        setRender(brick_fence_gate_magenta);

        setRender(brick_fence_orange);
        setRender(brick_fence_gate_orange);

        setRender(brick_fence_pink);
        setRender(brick_fence_gate_pink);

        setRender(brick_fence_purple);
        setRender(brick_fence_gate_purple);

        setRender(brick_fence_red);
        setRender(brick_fence_gate_red);

        setRender(brick_fence_silver);
        setRender(brick_fence_gate_silver);

        setRender(brick_fence_white);
        setRender(brick_fence_gate_white);

        setRender(brick_fence_yellow);
        setRender(brick_fence_gate_yellow);

        for (int i = 0; i < stainedBrickWallBlocks.length; i++) {
            setRender(stainedBrickWallBlocks[i]);
        }
        
        for (int i = 0; i < stainedBrickSlabBlocks.length; i++) {
            setRender(stainedBrickSlabBlocks[i]);
        }
    }

    private static void setRegister(Block block)
    {
        ForgeRegistries.BLOCKS.register(block);
        ForgeRegistries.ITEMS.register(new ItemBlock(block).setRegistryName(block.getRegistryName()));
    }

    public static void setRegister(Block block, ItemBlock itemBlock)
    {
        ForgeRegistries.BLOCKS.register(block);
        ForgeRegistries.ITEMS.register(itemBlock.setRegistryName(block.getRegistryName()));
    }

    @SideOnly(Side.CLIENT)
    private static void setRender(Block block)
    {
        Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(block), 0, new ModelResourceLocation(block.getRegistryName(), "inventory"));
        ModelBakery.registerItemVariants(
                Item.getItemFromBlock(block),
                new ModelResourceLocation(
                        "morematerials:" + block.getRegistryName(),
                        "variant=" + block.getRegistryName()));
    }

    @SideOnly(Side.CLIENT)
    private static void setRender(Block block, int meta_count, String[] meta_name)
    {
        for (int i = 0; i < meta_count; i++) {
            Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(block), i, new ModelResourceLocation(block.getRegistryName() + "_" + meta_name[i], "inventory"));
            ModelBakery.registerItemVariants(
                    Item.getItemFromBlock(block),
                    new ModelResourceLocation(
                            "morematerials:" + block.getRegistryName(),
                            "variant=" + block.getRegistryName() + "_" + meta_name[i]));
        }
    }
}

BlockStainedBrickSlab.class:
/**
 * Copyright (C) Jon Rowlett. All rights reserved.
 */
package de.shittyco.morematerials.blocks.slab;

import de.shittyco.morematerials.MoreMaterialsMod;
import de.shittyco.morematerials.utils.ColorUtility;
import de.shittyco.morematerials.utils.GameUtility;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.SoundType;
import net.minecraft.block.BlockSlab.EnumBlockHalf;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

/**
 * A slab or double slab of stained bricks of a certain color.
 * @author jrowlett
 *
 */
public abstract class BlockStainedBrickSlab extends BlockSlab {
    /**
     * The property used for the variant.
     * Needed for interactions with ItemSlab.
     */
    private static final PropertyBool VARIANT_PROPERTY = PropertyBool.create("variant");

    /**
     * The ID for the registry.
     */
    private static final String ID = "stained_bricks_slab";

    /**
     * The unlocalized name.
     */
    private static final String NAME = "stainedBricksSlab";

    /**
     * Hardness value for the material.
     */
    private static final float HARDNESS = 2.0f;

    /**
     * Resistance value for the material.
     */
    private static final float RESISTANCE = 10.0f;

    /**
     * The bit in metadata used by the half property.
     */
    private static final int HALF_META_BIT = 8;

    /**
     * Color - normally stored in metadata, but slabs need the meta.
     */
    private int color;

    /**
     * Sound when placing the block
     */
    private static SoundType soundType;

    /**
     * Initializes a new instance of the BlockStainedBrickSlab class.
     * @param brickColor the color of the stain from 0-15.
     */
    public BlockStainedBrickSlab(int brickColor) {
        super(Material.ROCK);
        this.color = brickColor;
        this.setRegistryName(getId());
        setUnlocalizedName(NAME + '_' + ColorUtility.COLOR_NAMES[this.color]);
        setHardness(HARDNESS);
        setResistance(RESISTANCE);
        //setStepSound(soundTypePiston);
        this.setSoundType(soundType.STONE);
        setCreativeTab(MoreMaterialsMod.creativeTab);

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

        this.setDefaultState(blockState);
        this.useNeighborBrightness = !this.isDouble();
    }
    
    /**
     * Gets the unlocalized name based on metadata/damage.
     * @param metadata block metadata.
     * @return the unlocalized name.
     */
    @Override
    public String getUnlocalizedName(int metadata) {
        return this.getUnlocalizedName();
    }
    
    /**
     * Gets the variant property.
     * @return the variant property null.
     */
    @Override
    public IProperty getVariantProperty() {
        return VARIANT_PROPERTY;
    }
    
    /**
     * Gets the value of the variant property based on the item.
     * @param itemStack item stack.
     * @return the variant value null.
     */
    //@Override
    //public final Object getVariant(final ItemStack itemStack) {
    //return false;
    //}
    
    @Override
    public Comparable<?> getTypeForItem(ItemStack stack) {
        return false;
    }

    /**
     * Gets the damage for the block's item when dropped.
     * @param state the block's state.
     * @return the metadata or color value.
     */
    @Override
    public int damageDropped(IBlockState state) {
        return 0;
    }
    
    /**
     * Gets a block state from metadata.
     * @param meta the metadata or color value.
     * @return a block state with the meta encoded as the variant property.
     */
    @Override
    public IBlockState getStateFromMeta(int meta) {
        IBlockState blockState = this.getDefaultState();
        blockState = blockState.withProperty(VARIANT_PROPERTY, false);
        if (!this.isDouble()) {
            EnumBlockHalf value = EnumBlockHalf.BOTTOM;
            if ((meta & HALF_META_BIT) != 0) {
                value = EnumBlockHalf.TOP;
            }

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

        return blockState;
    }
    
    /**
     * Gets the metadata value from a block state.
     * @param state the block state.
     * @return the metadata or color value.
     */
    @Override
    public int getMetaFromState(IBlockState state) {
        if (this.isDouble()) {
            return 0;
        }

        if ((EnumBlockHalf) state.getValue(HALF) == EnumBlockHalf.TOP) {
            return HALF_META_BIT;
        } else {
            return 0;
        }
    }
    
    /**
     * Gets the item dropped when the block is broken.
     * @param blockState the block's state.
     * @param random the random number generator
     * @param unused an integer.
     * @return the half slab item.
     */
    @Override
    public Item getItemDropped(IBlockState blockState, java.util.Random random, int unused) {
        String blockId = this.innerGetId(false);
        return GameUtility.getItemFromBlock(blockId);
    }

    /**
     * Creates the block state object.
     * @return the block state with properties defined.
     */
    @Override
    protected BlockStateContainer createBlockState() {
        if (this.isDouble())
        {
            return new BlockStateContainer(this, new IProperty[] {VARIANT_PROPERTY});
        }
        else
        {
            return new BlockStateContainer(this, new IProperty[] {VARIANT_PROPERTY, HALF});
        }
    }
    
    /**
     * Gets the ID for the game registry.
     * @return the unique id for the registry.
     */
    public String getId() {
        return this.innerGetId(this.isDouble());
    }

    /**
     * Gets the ID of the block.
     * @param isDoubleStacked override the isDouble() method.
     * @return the unique block id.
     */
    private String innerGetId(final boolean isDoubleStacked) {
        String result = "";
        if (isDoubleStacked) {
            result = "double_";
        }

        return result + ID + '_' + ColorUtility.COLOR_IDS[this.color];
    }

    /**
     * Gets the item dropped when the block is broken.
     * @param world the world
     * @param blockPos the block position.
     * @return the item dropped, the half slab.
     */
    /*
    @SideOnly(Side.CLIENT)
    @Override
    public final net.minecraft.item.Item getItem(
        final net.minecraft.world.World world,
        final net.minecraft.util.math.BlockPos blockPos,
        BlockStateContainer blockState) {
        String blockId = this.innerGetId(false);
        return GameUtility.getItemFromBlock(blockId);
    }
     */

    /**
     * Call on init to register the icons for inventory.
     * @param proxy the proxy to register the models.
     */
    /*
    public final void registerModels(final CommonProxy proxy) {
        Item itemBlock = GameUtility.getItemFromBlock(
            this.getId());
        proxy.addModelBakeryVariant(
            itemBlock,
            "morematerials:" + this.getId());
        proxy.registerInventoryModel(
            itemBlock,
            this.getId(),
            0);
    }
     */
}

ColorUtility.class:
/**
 * Copyright (C) Jon Rowlett. All rights reserved.
 */
package de.shittyco.morematerials.utils;

/**
 * Common Definitions and helpers for color.
 * @author jrowlett
 *
 */
public final class ColorUtility {

    /**
     * Common color names (unlocalized) indexed by item damage.
     */
    public static final String[] COLOR_NAMES = new String[] {
        "black",
        "red",
        "green",
        "brown",
        "blue",
        "purple",
        "cyan",
        "silver",
        "gray",
        "pink",
        "lime",
        "yellow",
        "lightBlue",
        "magenta",
        "orange",
        "white"
    };

    /**
     * Count of total colors.
     */
    public static final int COLOR_COUNT = COLOR_NAMES.length;

    /**
     * Common color tags used for icon name lookup indexed by item damage.
     */
    public static final String[] COLOR_IDS = new String[] {
        "black",
        "red",
        "green",
        "brown",
        "blue",
        "purple",
        "cyan",
        "silver",
        "gray",
        "pink",
        "lime",
        "yellow",
        "light_blue",
        "magenta",
        "orange",
        "white"
    };

    /**
     * Prevent instantiation of the ColorUtility class.
     */
    private ColorUtility() {
    }
}

blockstate: double_stained_bricks_slab_black.json:
{
    "variants": {
        "variant=false": { "model": "morematerials:stained_bricks_block_black" },
        "variant=true":    { "model": "morematerials:stained_bricks_block_black" }
    }
}

blockstate: stained_bricks_slab_black.json:
{
    "variants": {
        "half=bottom,variant=false": { "model": "morematerials:slab/half_slab_stained_bricks_black" },
        "half=top,variant=false": { "model": "morematerials:slab/upper_slab_stained_bricks_black" }
    }
}

model (block): half_slab_stained_bricks_black.json:
{
    "parent": "block/half_slab",
    "textures": {
        "bottom": "morematerials:blocks/stained_bricks_block_black",
        "top": "morematerials:blocks/stained_bricks_block_black",
        "side": "morematerials:blocks/stained_bricks_block_black"
    }
}

model (block): upper_slab_stained_bricks_black.json:
{
    "parent": "block/upper_slab",
    "textures": {
        "bottom": "morematerials:blocks/stained_bricks_block_black",
        "top": "morematerials:blocks/stained_bricks_block_black",
        "side": "morematerials:blocks/stained_bricks_block_black"
    }
}

model (item): stained_bricks_slab_black.json:
{
    "parent": "morematerials:block/slab/half_slab_stained_bricks_black",
    "display": {
        "thirdperson": {
            "rotation": [ 10, -45, 170 ],
            "translation": [ 0, 1.5, -2.75 ],
            "scale": [ 0.375, 0.375, 0.375 ]
        }
    }
}
 
7,099
324
1,510
blockstate: stained_bricks_slab_black.json:
{
    "variants": {
        "half=bottom,variant=false": { "model": "morematerials:slab/half_slab_stained_bricks_black" },
        "half=top,variant=false": { "model": "morematerials:slab/upper_slab_stained_bricks_black" },
        "half=double,variant=false": { "model": "morematerials:stained_bricks_block_black" }
    }
}
 
25
6
blockstate: stained_bricks_slab_black.json:
{
"variants": {
"half=bottom,variant=false": { "model": "morematerials:slab/half_slab_stained_bricks_black" },
"half=top,variant=false": { "model": "morematerials:slab/upper_slab_stained_bricks_black" },
"half=double,variant=false": { "model": "morematerials:stained_bricks_block_black" }
}
}

Это не помогло. У меня есть подозрения что этот блок тоже нужно как-то регистрировать. Но он же не должен появиться в инвентаре креатива, так как это будет дубль обычного блока
 
7,099
324
1,510
Это все тот же блок, просто в состоянии half он должен выглядеть также как и полный блок
~~~
@Override
protected BlockStateContainer createBlockState() {
if (this.isDouble())
{
return new BlockStateContainer(this, new IProperty[] {VARIANT_PROPERTY});
}
else
{
return new BlockStateContainer(this, new IProperty[] {VARIANT_PROPERTY, HALF});
}
}
В чем смысл? Двойная плита по идее должен быть тем же блоком, а не другим. А isDouble может меняться только со сменой блока
 
Последнее редактирование:
25
6
Называется, сам спросил, сам ответил)
В общем, нашёл, где была проблема. А именно в классе BlockStainedBrickSlab.class. Нужно было добавить строку ForgeRegistries.BLOCKS.register(this); в конец конструктора класса, поменять непонятные мне variants с PropertyBool на PropertyEnum и изменить связанные с ними методы:
BlockStainedBrickSlab.class:
/**
* Copyright (C) Jon Rowlett. All rights reserved.
*/
package de.shittyco.morematerials.blocks.slab;

import de.shittyco.morematerials.MoreMaterialsMod;
import de.shittyco.morematerials.utils.ColorUtility;
import de.shittyco.morematerials.utils.GameUtility;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.SoundType;
import net.minecraft.block.BlockSlab.EnumBlockHalf;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IStringSerializable;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

/**
[LIST]
[*]A slab or double slab of stained bricks of a certain color.
[*]@author jrowlett
[/LIST]
*
*/
public abstract class BlockStainedBrickSlab extends BlockSlab {
    /**
     * The property used for the variant.
     * Needed for interactions with ItemSlab.
     */
    //private static final PropertyBool VARIANT_PROPERTY = PropertyBool.create("variant");
    public static final PropertyEnum<Variant> VARIANT = PropertyEnum.<Variant>create("variant", Variant.class);

    /**
     * The ID for the registry.
     */
    private static final String ID = "stained_bricks_slab";

    /**
     * The unlocalized name.
     */
    private static final String NAME = "stainedBricksSlab";

    /**
     * Hardness value for the material.
     */
    private static final float HARDNESS = 2.0f;

    /**
     * Resistance value for the material.
     */
    private static final float RESISTANCE = 10.0f;

    /**
     * The bit in metadata used by the half property.
     */
    private static final int HALF_META_BIT = 8;

    /**
     * Color - normally stored in metadata, but slabs need the meta.
     */
    private int color;

    /**
     * Sound when placing the block
     */
    private static SoundType soundType;

    /**
     * Initializes a new instance of the BlockStainedBrickSlab class.
     * @param brickColor the color of the stain from 0-15.
     */
    public BlockStainedBrickSlab(int brickColor) {
        super(Material.ROCK);
        this.color = brickColor;
        this.setRegistryName(getId());
        setUnlocalizedName(NAME + '_' + ColorUtility.COLOR_NAMES[this.color]);
        setHardness(HARDNESS);
        setResistance(RESISTANCE);
        //setStepSound(soundTypePiston);
        this.setSoundType(soundType.STONE);
        setCreativeTab(MoreMaterialsMod.creativeTab);
        this.useNeighborBrightness = !this.isDouble();

        IBlockState state = this.blockState.getBaseState().withProperty(VARIANT, Variant.DEFAULT);
        if(!this.isDouble()) state = state.withProperty(HALF, EnumBlockHalf.BOTTOM);

        ForgeRegistries.BLOCKS.register(this);
    }

    /**
     * Gets the unlocalized name based on metadata/damage.
     * @param metadata block metadata.
     * @return the unlocalized name.
     */
    @Override
    public String getUnlocalizedName(int metadata) {
        return this.getUnlocalizedName();
    }

    /**
     * Gets the variant property.
     * @return the variant property null.
     */
    @Override
    public IProperty getVariantProperty() {
        return VARIANT;
    }

    /**
     * Gets the value of the variant property based on the item.
     * @param itemStack item stack.
     * @return the variant value null.
     */
    @Override
    public Comparable<?> getTypeForItem(ItemStack stack) {
        //return false;
        return Variant.DEFAULT;
    }

    public static enum Variant implements IStringSerializable
    {
        DEFAULT;

        @Override
        public String getName() {
            return "default";
        }
    }

    /**
     * Gets the damage for the block's item when dropped.
     * @param state the block's state.
     * @return the metadata or color value.
     */
    @Override
    public int damageDropped(IBlockState state) {
        return 0;
    }

    /**
     * Gets a block state from metadata.
     * @param meta the metadata or color value.
     * @return a block state with the meta encoded as the variant property.
     */
    @Override
    public IBlockState getStateFromMeta(int meta) {
        IBlockState state = this.blockState.getBaseState().withProperty(VARIANT, Variant.DEFAULT);

        if (!this.isDouble()) {
            EnumBlockHalf value = EnumBlockHalf.BOTTOM;
            if ((meta & 8) != 0) value = EnumBlockHalf.TOP;

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

        return state;
    }

    /**
     * Gets the metadata value from a block state.
     * @param state the block state.
     * @return the metadata or color value.
     */
    @Override
    public int getMetaFromState(IBlockState state) {
        int meta = 0;
        if(!this.isDouble() && state.getValue(HALF) == EnumBlockHalf.TOP) meta |= 8; 
        return meta;
    }

    /**
     * Gets the item dropped when the block is broken.
     * @param blockState the block's state.
     * @param random the random number generator
     * @param unused an integer.
     * @return the half slab item.
     */
    @Override
    public Item getItemDropped(IBlockState blockState, java.util.Random random, int unused) {
        String blockId = this.innerGetId(false);
        return GameUtility.getItemFromBlock(blockId);
    }

    /**
     * Creates the block state object.
     * @return the block state with properties defined.
     */
    @Override
    protected BlockStateContainer createBlockState() {
        if(!this.isDouble())
            return new BlockStateContainer(this, new IProperty[] {VARIANT, HALF});
        else
            return new BlockStateContainer(this, new IProperty[] {VARIANT});
    }

    /**
     * Gets the ID for the game registry.
     * @return the unique id for the registry.
     */
    public String getId() {
        return this.innerGetId(this.isDouble());
    }

    /**
     * Gets the ID of the block.
     * @param isDoubleStacked override the isDouble() method.
     * @return the unique block id.
     */
    private String innerGetId(final boolean isDoubleStacked) {
        String result = "";
        if (isDoubleStacked) {
            result = "double_";
        }

        return result + ID + '_' + ColorUtility.COLOR_IDS[this.color];
    }
}

Ну и, соответственно, изменил blockstates:
double_stained_bricks_slab_black.json:
{
    "variants":
    {
        "variant=default": { "model": "morematerials:stained_bricks_block_black" }
    }
}

stained_bricks_slab_black.json:
{
    "variants":
    {
        "half=bottom,variant=default": { "model": "morematerials:slab/half_slab_stained_bricks_black" },
        "half=top,variant=default": { "model": "morematerials:slab/upper_slab_stained_bricks_black" }
    }
}

Может кому поможет, кто столкнётся с такими же сложностями
Кстати, в учебнике очень мало инфы о состояниях блока. Там только про PropertyBool говорится, про остальные ничего нет, пришлось искать на других ресурсах, в основном зарубежных
 
Последнее редактирование:
Сверху