Состояния блока

Версия Minecraft
1.12.2
API
Forge

sk9zist :l

Исправился
981
18
158
Никак не могу понять, как сделать разную текстуру для каждой стороны блока из состояния блока. Разную текстуру для каждой стороны обычного блока я могу сделать, но я непонимаю как делать текстуры для блока с состояниями, там какая-то замороченная хрень...
BlocksRegister.java:
public class BlocksRegister
{
    public static final Block VM = new BlockVendingMachine("vm");

    public static void register()
    {
        setRegister(VM);
    }

    @SideOnly(Side.CLIENT)
    public static void registerRender()
    {
        setRender(VM);
    }

    private static void setRegister(Block block)
    {
        ForgeRegistries.BLOCKS.register(block);
        ForgeRegistries.ITEMS.register(new ItemBlock(block).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"));
    }
}
BlockVendingMachine.java:
public class BlockVendingMachine extends BlockHorizontal
{
    public static final PropertyEnum<BlockVendingMachine.EnumPartType> PART = PropertyEnum.create("part", BlockVendingMachine.EnumPartType.class);
    //protected static final AxisAlignedBB TABLE_AABB = new AxisAlignedBB(0.0, 0.0, 0.0, 1.0 ,0.5625, 1.0);
    
    public BlockVendingMachine(String name)
    {
        super(Material.IRON);
        this.setRegistryName(name);
        this.setUnlocalizedName(name);
        this.setHardness(0.01f);
        this.setDefaultState(this.blockState.getBaseState().withProperty(PART, EnumPartType.FOOT));
    }
    
    @Override
    public boolean isFullCube(IBlockState state)
    {
        return false;
    }
    
    @Override
    public boolean isOpaqueCube(IBlockState state)
    {
        return  false;
    }
    
    /*@Override
    public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
    {
        return TABLE_AABB;
    }*/
    
    @Override
    protected BlockStateContainer createBlockState()
    {
        return new BlockStateContainer(this, new IProperty[] {PART});
    }
    
    public static enum EnumPartType implements IStringSerializable
    {
        HEAD("head"),
        FOOT("foot");

        private final String name;

        private EnumPartType(String name)
        {
            this.name = name;
        }

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

        public String getName()
        {
            return this.name;
        }
    }
    
    @Override
    public IBlockState getStateFromMeta(int meta)
    {
        if (meta == 0) {
            return this.getDefaultState().withProperty(PART, EnumPartType.FOOT);
        }
        if (meta == 1) {
            return this.getDefaultState().withProperty(PART, EnumPartType.HEAD);
        }
        return this.getDefaultState().withProperty(PART, EnumPartType.FOOT);
    }
    
    @Override
    public int getMetaFromState(IBlockState state)
    {
        int i = 0;
        if (state.getValue(PART) == EnumPartType.HEAD)
        {
            i = 1;
        }

        return i;
    }
    
    @Override
    public void onBlockHarvested(World worldIn, BlockPos pos, IBlockState state, EntityPlayer player) {
        if (state.getValue(PART) == EnumPartType.FOOT) {
            worldIn.setBlockState(pos.up(1), Blocks.AIR.getDefaultState());
        }
        else if (state.getValue(PART) == EnumPartType.HEAD) {
            worldIn.setBlockState(pos.down(1), Blocks.AIR.getDefaultState());
        }
    }
}
ClientProxy в init:
BlocksRegister.registerRender();
CommonProxy в preInit:
BlocksRegister.register();

папка blockstates:
vm.json:
{
  "variants": {
    "part=foot": { "model": "ngem:foot" },
    "part=head": { "model": "ngem:head" }
  }
}
папка models/block:
vendingMachine_2.json:
{
    "parent": "block/vm",
    "textures": {
        "texture": "ngem:blocks/vendingMachine_2"
    }
}
head.json:
{
    "textures": {
        "0": "minecraft:blocks/log_oak",
        "particle": "minecraft:blocks/log_oak"
    }
}
vm.json:
{
    "parent": "block/orientable",
    "textures": {
       "up": "ngem:blocks/vendingMachine_0",
       "down": "ngem:blocks/vendingMachine_0",
       "south": "ngem:blocks/vendingMachine_2",
       "north": "ngem:blocks/vendingMachine_3",
       "west": "ngem:blocks/vendingMachine_3",
       "east": "ngem:blocks/vendingMachine_3"
   }
}

папка models/item:
foot.json:
{
    "textures": {
        "0": "minecraft:blocks/log_oak",
        "particle": "minecraft:blocks/log_oak"
    }
}
head.json:
{
    "textures": {
        "0": "minecraft:blocks/log_oak",
        "particle": "minecraft:blocks/log_oak"
    }
}
vm.json:
{
  "parent": "item/generated",
  "textures": {
  "layer0":"ngem:items/vm"
  }
}

файлы в textures/items:
vm.png
vm.png
файлы в textures/blocks:
vendingMachine_0.pngvendingMachine_1.pngvendingMachine_2.pngvendingMachine_3.pngvendingMachine_4.png
vendingMachine_0.png, vendingMachine_1.png, vendingMachine_2.png, vendingMachine_3.png, vendingMachine_4.png

Уже и в ванили смотрел, и на форуме искал - ничего не понимаю. Стейты в моем блоке - head и foot. Это многоблочная структура которую я сделал по туториалу уважаемого ReyMagos:

Как сделать разную текстуру для каждой стороны каждого блока структуры (два блока)? Мне нужно просто поставить текстуры чтобы она смотрела в одном направлении, т.е. мета и установка этой текстуры по взгляду игрока не нужна
 
Теория коротко:
у блока может быть 16 вариантов блокстейта
у каждого блокстейта может быть своя модель
Таким образом, без некоторых хаков твой блок может выглядеть16 различными способами, будь то отличие в текстурках или форме

Как сделать:
  • в своем блоке правильно определить createBlockState, getStateFromMeta, getMetaFromState, полагаю, ты уже это сделал
  • в файле /assets/<modid>/blockstates/<block_registry_name_path>.json указать соответствия моделей для каждого варианта блока
JSON:
{
  "variants": {
    "prop1=value1,property2=value1":  { "model": "modid:model1" },
    "prop1=value2,property2=value1":  { "model": "modid:model2" },
    "prop1=value1,property2=value2":  { "model": "modid:model3" },
    "prop1=value2,property2=value2":  { "model": "modid:model4" }
  }
}
  • создать соответствующие модели
 
создать соответствующие модели
А как? Файл, подобный тому что ты скинул выше у меня уже есть. Остается вопрос только в том какие файлы и где создавать для моделей. Причём у каждой модели каждого блокстейта (а их всего два) должны быть вариации текстур для верхней, нижней, северной, восточной, западной, южной сторон (up, down, west, east, south, north)
 
Модели располагаются в /assets/<modid>/models/block/<model_name>.json

Причём у каждой модели каждого блокстейта (а их всего два) должны быть вариации текстур для верхней, нижней, северной, восточной, западной, южной сторон
Одна модель - один визуальный облик, текстуры не меняются. Или это уже будет другая модель
 
Одна модель - один визуальный облик, текстуры не меняются. Или это уже будет другая модель
Не понял. А как тогда устроен json файл модели печки?
Вот он:
furnace.json:
{
    "parent": "block/orientable",
    "textures": {
        "top": "blocks/furnace_top",
        "front": "blocks/furnace_front_off",
        "side": "blocks/furnace_side"
    }
}
 
Это одна модель и она статичная. У нее на верхнем полигоне всегда текстура blocks/furnace_top, на переднем полигоне - blocks/furnace_front_off, на всех остальных полигонах - blocks/furnace_side.
Однако, печку можно поставить разными сторонами - тебя это смущает? Взгляни в ее жисон блокстейт, там можно видеть, что для каждого варианта блокстейта применяется разные вращения модели
 
Ну а у меня даже статичную модель не получается сделать... Чтобы была сверху одна текстура, спереди еще одна а со всех других сторон - другая.
Я вроде бы все файлы создал правильно, по пути /assets/<modid>/models/block/<model_name>.json
Вот:
папка models/block:
Java:
{
"parent": "block/vm",
"textures": {
"texture": "ngem:blocks/vendingMachine_2"
}
}
Java:
{
"textures": {
"0": "minecraft:blocks/log_oak",
"particle": "minecraft:blocks/log_oak"
}
}
Java:
{
"parent": "block/orientable",
"textures": {
"up": "ngem:blocks/vendingMachine_0",
"down": "ngem:blocks/vendingMachine_0",
"south": "ngem:blocks/vendingMachine_2",
"north": "ngem:blocks/vendingMachine_3",
"west": "ngem:blocks/vendingMachine_3",
"east": "ngem:blocks/vendingMachine_3"
}
}
 
три файла по каким путям лежат?
в эта папка: /assets/<modid>/models/block/
Вот кстати, извиняюсь, забыл прикрепить скриншот в шапке и в сообщении выше (там должен был быть он):
2021-10-13_23.08.38.png
Как выглядит. В последнее время вроде текстуры вообще прозрачные стали
 
Последнее редактирование:
Попробуй сначала более простую задачу решить: блок с моделью у которой на каждой стороне разная текстура. А потом усложни: добавь блоку варианты и каждому варианту назначь разную модель
 
Получилось. Проблема была лишь в названии файлов текстур... Изменил с "vendingMachine_0" на "vm_0" и всё заработало.
А как теперь сделать установку этих текстур в зависимости от того с какой стороны света кликнул игрок и поставил блок?
2021-10-16_15.25.07.png
 
Изменил с "vendingMachine_0" на "vm_0" и всё заработало.
Подозреваю, что проблема была в регистре. Нужно все в нижнем
А как теперь сделать установку этих текстур в зависимости от того с какой стороны света кликнул игрок и поставил блок?
Печка имеет пропертю для этого
Количество вариантов умножается на 4
Каждому варианту назначается своя модель
Следи за тем, чтобы количество вариантов не превысило 16
 
Следи за тем, чтобы количество вариантов не превысило 16
А каким образом оно может превысить 16?

Сделал так, правильно ли это?
Java:
@Override
    protected BlockStateContainer createBlockState()
    {
        return new BlockStateContainer(this, new IProperty[] {PART,FACING});
    }
Java:
@Override
    public IBlockState getStateFromMeta(int meta)
    {
        EnumFacing facing = EnumFacing.getFront(meta % 4);
        if(facing.getAxis() == EnumFacing.Axis.Y) facing = EnumFacing.NORTH;
        
        if (meta == 0) {
            return this.getDefaultState().withProperty(PART, EnumPartType.FOOT);
        }
        if (meta == 1) {
            return this.getDefaultState().withProperty(PART, EnumPartType.HEAD);
        }
        return this.getDefaultState().withProperty(PART, EnumPartType.FOOT).withProperty(FACING, EnumFacing.values()[meta]);
    }

А еще не понимаю как правильно можно сделать вот тут:
Java:
@Override
    public int getMetaFromState(IBlockState state)
    {
        int i = 0;
        if (state.getValue(PART) == EnumPartType.HEAD)
        {
            i = 1;
        }

        return i;
        
        // Вот это нужно как-то добавить/совместить:
        return state.getValue(FACING).ordinal();
    }
 
UP
 
UP
 
UP
 
UP
 
Почитай про битовый операции.
Тебе нужно что-то типа: (state.getValue(FACING).getHorizontalIndex() << 1) | state.getValue(PART).ordinal()

А ещё, так как блока на самом деле два, то используя метод getActualState() можно увеличить количество состояний до 64-х )))
 
Назад
Сверху