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

Версия Minecraft
1.12.2
API
Forge

sk9zist :l

Исправился
981
18
157
Никак не могу понять, как сделать разную текстуру для каждой стороны блока из состояния блока. Разную текстуру для каждой стороны обычного блока я могу сделать, но я непонимаю как делать текстуры для блока с состояниями, там какая-то замороченная хрень...
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:

Как сделать разную текстуру для каждой стороны каждого блока структуры (два блока)? Мне нужно просто поставить текстуры чтобы она смотрела в одном направлении, т.е. мета и установка этой текстуры по взгляду игрока не нужна
 
7,099
324
1,510
Теория коротко:
у блока может быть 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" }
  }
}
  • создать соответствующие модели
 

sk9zist :l

Исправился
981
18
157
создать соответствующие модели
А как? Файл, подобный тому что ты скинул выше у меня уже есть. Остается вопрос только в том какие файлы и где создавать для моделей. Причём у каждой модели каждого блокстейта (а их всего два) должны быть вариации текстур для верхней, нижней, северной, восточной, западной, южной сторон (up, down, west, east, south, north)
 
7,099
324
1,510
Модели располагаются в /assets/<modid>/models/block/<model_name>.json

Причём у каждой модели каждого блокстейта (а их всего два) должны быть вариации текстур для верхней, нижней, северной, восточной, западной, южной сторон
Одна модель - один визуальный облик, текстуры не меняются. Или это уже будет другая модель
 

sk9zist :l

Исправился
981
18
157
Одна модель - один визуальный облик, текстуры не меняются. Или это уже будет другая модель
Не понял. А как тогда устроен json файл модели печки?
Вот он:
furnace.json:
{
    "parent": "block/orientable",
    "textures": {
        "top": "blocks/furnace_top",
        "front": "blocks/furnace_front_off",
        "side": "blocks/furnace_side"
    }
}
 
7,099
324
1,510
Это одна модель и она статичная. У нее на верхнем полигоне всегда текстура blocks/furnace_top, на переднем полигоне - blocks/furnace_front_off, на всех остальных полигонах - blocks/furnace_side.
Однако, печку можно поставить разными сторонами - тебя это смущает? Взгляни в ее жисон блокстейт, там можно видеть, что для каждого варианта блокстейта применяется разные вращения модели
 

sk9zist :l

Исправился
981
18
157
Ну а у меня даже статичную модель не получается сделать... Чтобы была сверху одна текстура, спереди еще одна а со всех других сторон - другая.
Я вроде бы все файлы создал правильно, по пути /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"
}
}
 

sk9zist :l

Исправился
981
18
157
три файла по каким путям лежат?
в эта папка: /assets/<modid>/models/block/
Вот кстати, извиняюсь, забыл прикрепить скриншот в шапке и в сообщении выше (там должен был быть он):
2021-10-13_23.08.38.png
Как выглядит. В последнее время вроде текстуры вообще прозрачные стали
 
Последнее редактирование:
7,099
324
1,510
Попробуй сначала более простую задачу решить: блок с моделью у которой на каждой стороне разная текстура. А потом усложни: добавь блоку варианты и каждому варианту назначь разную модель
 

sk9zist :l

Исправился
981
18
157
Получилось. Проблема была лишь в названии файлов текстур... Изменил с "vendingMachine_0" на "vm_0" и всё заработало.
А как теперь сделать установку этих текстур в зависимости от того с какой стороны света кликнул игрок и поставил блок?
2021-10-16_15.25.07.png
 
7,099
324
1,510
Изменил с "vendingMachine_0" на "vm_0" и всё заработало.
Подозреваю, что проблема была в регистре. Нужно все в нижнем
А как теперь сделать установку этих текстур в зависимости от того с какой стороны света кликнул игрок и поставил блок?
Печка имеет пропертю для этого
Количество вариантов умножается на 4
Каждому варианту назначается своя модель
Следи за тем, чтобы количество вариантов не превысило 16
 

sk9zist :l

Исправился
981
18
157
Следи за тем, чтобы количество вариантов не превысило 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();
    }
 

sk9zist :l

Исправился
981
18
157
UP
 

sk9zist :l

Исправился
981
18
157
UP
 

sk9zist :l

Исправился
981
18
157
UP
 

sk9zist :l

Исправился
981
18
157
UP
 
4,045
63
645
Почитай про битовый операции.
Тебе нужно что-то типа: (state.getValue(FACING).getHorizontalIndex() << 1) | state.getValue(PART).ordinal()

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