Иконка ресурса

Блоки с метадатой.(как шерсть, цемент)

Версия(и) Minecraft
1.12.2
Всем привет! Уже не первый раз встречаю вопросы как сделать блоки метадатой. Недавно сам разобрался, и вот решил рассказать и вам.
Начать следует с того, что же такое блоки с метой? Метадата, а правильнее - подтип. То есть например, вы все знаете что есть дерево. Просто дерево. А дерево - слишком общее понятие. Ведь есть и дерево - береза, дуб, ель, сосна... и так далее.
Это и есть метаблоки.
Итак, приступим. В майне в новых версиях есть 4 вида камня - обычный, гранит, диорит и андезит. Но булыга есть только для обычного... непорядок? Давайте добавим булыгу всех видов для остальных камней.
Оговорюсь - гайд не для прям новичков, поэтому объяснять все подробно не буду.

Сначала создадим блок, имеющий субтипы, аналогично предмету.
Java:
public class BlockCobblestones extends BasicBlockFalling
{
    public static final PropertyEnum<BlockCobblestones.EnumType> VARIANT = PropertyEnum.<BlockCobblestones.EnumType>create("variant", BlockCobblestones.EnumType.class);

    public BlockCobblestones(String name, float hardness, float resistanse , SoundType soundtype)
    {
        super(Material.ROCK, name, resistanse, resistanse, soundtype);
        this.setDefaultState(this.blockState.getBaseState().withProperty(VARIANT, BlockCobblestones.EnumType.COBBLE_ANDESITE));
        this.setCreativeTab(CreativeTabs.BUILDING_BLOCKS);

    }

    public int damageDropped(IBlockState state)
    {
        return ((BlockCobblestones.EnumType)state.getValue(VARIANT)).getMetadata();
    }
//метод позволяющий нам указать, откуда брать субтипы.
    public void getSubBlocks(CreativeTabs itemIn, NonNullList<ItemStack> items)
    {
        for (BlockCobblestones.EnumType blockstone$enumtype : BlockCobblestones.EnumType.values())
        {
            items.add(new ItemStack(this, 1, blockstone$enumtype.getMetadata()));
        }
    }

    public IBlockState getStateFromMeta(int meta)
    {
        return this.getDefaultState().withProperty(VARIANT, BlockCobblestones.EnumType.byMetadata(meta));
    }

    public int getMetaFromState(IBlockState state)
    {
        return ((BlockCobblestones.EnumType)state.getValue(VARIANT)).getMetadata();
    }
//обязательно создаем контейнер стейтов
    protected BlockStateContainer createBlockState()
    {
        return new BlockStateContainer(this, new IProperty[] {VARIANT});
    }
//перечисление наших подтипов
    public static enum EnumType implements IStringSerializable
    {
        COBBLE_GRANITE(0, MapColor.DIRT, "granite", true),
        COBBLE_DIORITE(1, MapColor.QUARTZ, "diorite", true),
        COBBLE_ANDESITE(2, MapColor.STONE, "andesite", true);

        private static final BlockCobblestones.EnumType[] META_LOOKUP = new BlockCobblestones.EnumType[values().length];
        private final int meta;
        private final String name;
        private final String unlocalizedName;
        private final MapColor mapColor;
        private final boolean isNatural;

        private EnumType(int meta, MapColor mapColor, String name, boolean isNatural)
        {
            this(meta, mapColor, name, name, isNatural);
        }

        private EnumType(int meta, MapColor mapColor, String name, String Uname, boolean isNatural)
        {
            this.meta = meta;
            this.name = name;
            this.unlocalizedName = Uname;
            this.mapColor = mapColor;
            this.isNatural = isNatural;
        }

        public int getMetadata()
        {
            return this.meta;
        }

        public MapColor getMapColor()
        {
            return this.mapColor;
        }

        public String toString()
        {
            return this.name;
        }

        public static BlockCobblestones.EnumType byMetadata(int meta)
        {
            if (meta < 0 || meta >= META_LOOKUP.length)
            {
                meta = 0;
            }

            return META_LOOKUP[meta];
        }

        public String getName()
        {
            return this.name;
        }

        public String getUnlocalizedName()
        {
            return this.unlocalizedName;
        }

        public boolean isNatural()
        {
            return this.isNatural;
        }

        static
        {
            for (BlockCobblestones.EnumType blockstone$enumtype : values())
            {
                META_LOOKUP[blockstone$enumtype.getMetadata()] = blockstone$enumtype;
            }
        }
    }
}
Также нам необходимо создать itemBlock для наших блоков, чтобы они корректно отображались в инвентаре.
Java:
public class ItemBlockCobblestones extends ItemMultiTexture{

    public ItemBlockCobblestones(Block block) {
        super(block, block, new String[] {"cobble_andesite","cobble_diorite","cobble_granite"} );
        this.setHasSubtypes(true);
    }
//создаем субтипы итемов, в котором вызываем субтипы блоков
    @Override
    public void getSubItems(CreativeTabs tab, NonNullList<ItemStack> items)
    {
        if (this.isInCreativeTab(tab))
        {
   
            this.block.getSubBlocks(tab, items);
        }
    }
    @Override
    public String getUnlocalizedName(ItemStack stack)
    {
        return super.getUnlocalizedName() + "." + EnumType.byMetadata(stack.getMetadata()).getName();
    }
}
В принципе это все. Осталось зарегистрировать блок и отдельно модели.
Java:
public static Block cobblestones = new BlockCobblestones("cobblestones", 6F, 1, SoundType.WOOD);
//этот метод соотвественно регается в прокси и вообще все делаем как положено.
    public static void register() {
        //обычно мы регистрируем так.
        registerBlock(jungle_stage_1);
        //но для нашей цели это не подойдет. давайте создаим специальный метод, который свяжет итемблоки и блоки.
        registerBlockMeta(cobblestones, new ItemBlockCobblestones(cobblestones));
    }
    //просто добавим параметр итем блок, к привычной нам регистрации
    public static void registerBlockMeta(Block block, ItemBlock itemBlock) {
    ForgeRegistries.BLOCKS.register(block);
    ForgeRegistries.ITEMS.register(itemBlock.setRegistryName(block.getRegistryName()));
    }
Ну а теперь, зайдя в игру, мы увидим наши блоки... в мир все ставится великолепно... но у них нету моделей в инвентаре! Ах... Такое дело надо регистрировать отдельно, вот так:
Класс RegMetaBlocks надлежит регистрировать в ClientProxy, в preInit
MinecraftForge.EVENT_BUS.register(new RegMetaBlocks());
Java:
public class RegMetaBlocks {
//сетаем кастомный модельресурслокейшн. Регаем через ModelRegistryEvent.
    @SubscribeEvent
    public void registerMetaBlocks(ModelRegistryEvent e) {
            register(RegBlocks.cobblestones);
    }


    public void register(Block block)
    {
        for(BlockCobblestones.EnumType type : BlockCobblestones.EnumType.values())
        {
            ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), type.getMetadata(), new ModelResourceLocation(block.getRegistryName() + "_" + type.getName(), "inventory"));
        }
    }
}
Теперь осталось последнее: в json-файлах создаем блокстейт с вариантами
JSON:
{
  "variants": {
    "variant=granite": { "model": "realism:cobble_granite" },
    "variant=diorite": { "model": "realism:cobble_diorite" },
    "variant=andesite": { "model": "realism:cobble_andesite" }
  }
}
Соотвественно, модели предметам, блокам делаем в jsonах, все как обычно.
Ну вот и все.
Заходим в игру, радуемся нашей кобле.
2018-08-01_18.52.28.png
Автор
Maxik
Просмотры
1,229
Первый выпуск
Обновление
Оценка
5.00 звёзд 3 оценок

Другие ресурсы пользователя Maxik

Последние рецензии

Отличный гайд, по идее полезный.
Достаточно подробно описан.
Пример с коблой довольно практичен и понятен.
Но я просто регаю новые экземпляры блока для каждого подтипа, кода меньше
Maxik
Maxik
но больше json-нов))
Полезно, не хватает только каких-то хитростей, типа прочность на мете, или тп.
Maxik
Maxik
как нибудь, добавлю и такое. Хотя я вот даже не знаю, возможно ли это.
Сверху