Элегантный способ получать IIcon стороны блока с учетом направления и разных текстур под разные стороны

Версия Minecraft
1.7.10
1,159
38
544
Здравствуйте народ. У меня встала довольно обыденная задача - сделать блок с лицевой стороной, способный поворачиваться к игроку при установке, и имеющий разные текстуры для каждой из сторон блока. Т.е. по сути реализовать поведение печки.

Обычно я копипащу код аналогичных блоков, но сегодня моем терпению пришел конец. Видеть подобное я больше не в состоянии:
BlockFurnace:
@SideOnly(Side.CLIENT)
public IIcon getIcon(int p_149691_1_, int p_149691_2_)
{
    return p_149691_1_ == 1 ? this.field_149935_N : (p_149691_1_ == 0 ? this.field_149935_N : (p_149691_1_ != p_149691_2_ ? this.blockIcon : this.field_149936_O));
}

Читать такое крайне сложно. Поэтому я попытался найти более читаемое решение, но лучше не стало:
MyDirectionalBlock:
override fun getIcon(side: Int, meta: Int): IIcon {
        return if (side == 1) sides[0]
               else if (side == 0) sides[0]
               else if (meta == 2 && side == 2) sides[2]
               else if (meta == 0 && side == 3) sides[2]
               else if (meta == 1 && side == 4) sides[2]
               else if (meta == 3 && side == 5) sides[2]

               else if (meta == 0 && side == 2) sides[3]
               else if (meta == 2 && side == 3) sides[3]
               else if (meta == 3 && side == 4) sides[3]
               else if (meta == 1 && side == 5) sides[3]

               else super.getIcon(side, meta)
}

Как я могу сделать код getIcon() лучше, когда у меня есть несколько текстур под разные стороны блока и требование поворачиваться лицевой стороной к игроку при установке?

UPD: Решение
 
Последнее редактирование:
Решение
Способ выше работал криво. Я нашел окончательный вариант решения, который меня удовлетворил:
MyDirectionalBlock.java:
@SideOnly(Side.CLIENT)
@Override
public IIcon getIcon(int side, int meta) {
//    sides[0] = blockIconTop; // низ
//    sides[1] = blockIconTop; // верх
//    sides[2] = blockIconFront; // север
//    sides[3] = blockIcon; // юг
//    sides[4] = blockIcon; // запад
//    sides[5] = blockIcon; // восток

    switch (side) {
        case 0:return sides[0];
        case 1:return sides[1];
        default: {
            // Direction#bedDirection хранит индексы иконок для каждой из сторон блоков с учетом направления.
            // Direction#bedDirection является двумерным массом, который располагает наборами таких индексов для
            // юга...
1,159
38
544
Способ выше работал криво. Я нашел окончательный вариант решения, который меня удовлетворил:
MyDirectionalBlock.java:
@SideOnly(Side.CLIENT)
@Override
public IIcon getIcon(int side, int meta) {
//    sides[0] = blockIconTop; // низ
//    sides[1] = blockIconTop; // верх
//    sides[2] = blockIconFront; // север
//    sides[3] = blockIcon; // юг
//    sides[4] = blockIcon; // запад
//    sides[5] = blockIcon; // восток

    switch (side) {
        case 0:return sides[0];
        case 1:return sides[1];
        default: {
            // Direction#bedDirection хранит индексы иконок для каждой из сторон блоков с учетом направления.
            // Direction#bedDirection является двумерным массом, который располагает наборами таких индексов для
            // юга (0), запада (1), севера (3) и востока (3). Вы можете видеть, что эта схема отличная от
            // принятой в игре системы обозначения сторон: север (2), юг (3), запад (4), восток (5), поэтому
            // для возможности работать с bedDirection мы преобразуем метадату, которая хранит направление блока
            // в принятом в игре формате, к диапазону чисел от 0 до 3. Массив Direction#facingToDirection как
            // раз создан для выполнения такого преобразования.
            int direction = Direction.facingToDirection[meta];
            // После того как мы получили направление в диапазоне от 0 до 3, мы можем использовать его для получения
            // индексов иконок для каждой из сторон блока с учетом направления.
            int index = Direction.bedDirection[direction][side];
            // Результатом будет индекс икноки, которую нам нужно вернуть. Важно сказать что это срабоает только
            // если массив ваших иконок придерживается следующей схеме: 0 - низ, 1 - верх, 2 - север, 3 - юг,
            // 4 - запад, 5 - восток. Т.е. придерживается схеме направлений, принятой в игре.
            return sides[index];
            
            // или коротко:
            // return sides[Direction.bedDirection[Direction.facingToDirection[meta]][side]];
        }
    }
}

Я считаю это решение лучшим, т.к. оно полностью основано на ванильном коде и не вынуждает нас выделять массивы индексов, юзать мапу или реализовывать блокстейты из 1.12.2. Надеюсь что это будет кому-то полезно.

2020-06-27_15.09.00.png

2020-06-27_15.09.05.png

2020-06-27_15.09.10.png

2020-06-27_15.09.18.png

2020-06-27_15.09.28.png

Благодарю всех участников обсуждения за внесения вклада в поиск лучшего решения.

БОНУС:
Хотите быстро проверять будет ли ваш блок отрисовывать правильную текстуру на каждой грани в зависимости от поворота? Воспользуйтесь этим юнит-тестом:
TestBlockDirectional.java:
package com.example.examplemod.blocks;

import net.minecraft.block.material.Material;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

// Требуется junit5
public class TestBlockDirectional {

    // [meta]
    // 2 (north), 3 (south), 4 (west), 5 (east)
    private static final int[][] indexes = {{2,3,4,5}, {3,2,5,4}, {5,4,2,3}, {4,5,3,2}};

    private static final YOUR_BLOCK block = new YOUR_BLOCK();

    [USER=8243]@Test[/USER]
    public void getIcon() {
        for (int meta = 2; meta < 6; meta++) {
            for (int side = 2; side < 6; side++) {
                // создайте в блоке функцию getIconIndex()
                assertEquals(indexes[meta-2][side-2], block.getIconIndex(side, meta),
                        String.format("(meta=%d, side=%d)", meta, side));
            }
        }
    }

}
 
Сверху