Метадата и поворот блока

Версия Minecraft
1.7.10
1,159
38
544
Доброго времени суток и с наступающим, дорогие форумчане! Я хочу встретить новый год с чистой совестью, а потому желаю отрефакторить определение поворота в своем кастомном блоке.

Сейчас я сохраняю мету в NBT и синхронизирую это дело через TileEntity#getDescriptionPacket()
fdf683c8c68bb41b3c95bdddcc3fe043.jpg

UpgradeStationEntity.java:
public class UpgradeStationEntity extends TileEntity {
    
    ...

    // TODO: Сохранять направление в NBT - нерационально. Нужно юзать метадату - http://www.minecraftforge.net/forum/topic/25239-solved1710-saving-block-direction-state/
    @Override
    public void writeToNBT(NBTTagCompound compound) {
        super.writeToNBT(compound);
        upgradeStationInventory.writeToNBT(compound); // TODO: Синхронизировать инвентарь на уровне тайла - это просто дно. Не тайл синхронизирут инвентарь, а открытый игроком контейнер!
        compound.setInteger("dir", this.blockMetadata);
    }

    @Override
    public void readFromNBT(NBTTagCompound compound) {
        super.readFromNBT(compound);
        upgradeStationInventory.readFromNBT(compound);
        this.blockMetadata = compound.getInteger("dir");

    }

    // TODO: Отказаться от хранения поворота в NBT. Это следует делать в метадате блока как в печке!
    // Синхронизирует переменные блока с блоком на клиенте
    @Override
    public Packet getDescriptionPacket() {
        NBTTagCompound tag = new NBTTagCompound();
        writeToNBT(tag);
        return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 0, tag);
    }

    // Нужно для метода выше
    @Override
    public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
        readFromNBT(pkt.func_148857_g());
    }

    // http://cazzar.net/tutorials/minecraft/Tile-Entity-Updates-The-Quick-and-Dirty-Method/
    public void markForUpdate() {
        worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
    }
}

Ужас! Дед мороз точно мне ничего не подарит, если я оставлю это все как есть.

Я решил сделать определение лицевой стороны в своем блоке точно таким же способом, как и в ванильном коде. Всем известно, что за направление блока отвечает его метадата. Но вот ее вычисление в некоторых местах сбивает меня с толку. Давайте для начала взглянем на код печки (в ванильный код я добавил некоторые пояснения):
BlockFurnace.java:
public void onBlockPlacedBy(World p_149689_1_, int p_149689_2_, int p_149689_3_, int p_149689_4_, EntityLivingBase p_149689_5_, ItemStack p_149689_6_)
{
    // Стандартное вычисление направления, в которое должна смотреть морда блока
    // Результатом вычислений будет int, описывающий одну из сторон света
    int l = MathHelper.floor_double((double)(p_149689_5_.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
    
    if (l == 0) // Север (отрицателный z)
    {
        p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 2, 2);
    }

    if (l == 1) // Восток (положительный x)
    {
        p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 5, 2);
    }

    if (l == 2) // Юг (положительный z)
    {
        p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 3, 2);
    }

    if (l == 3) // Запад (отрицательный x)
    {
        p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 4, 2);
    }

    ...
}

Все довольно просто, но почему печка подставляет вместо меты не вычисленное значение, а иные константы: 2 (север), 3 (юг), 4 (восток), 5 (запад)? Может константы 1 и 2 используются печкой для обозначения чего-то еще? В таком случае у меня не получается найти где используются значения 1 и 2. Такая же ситуация кстати и с наковальней, поршнем, сундуком и другими блоками. Однако BlockCocoa сразу юзает результат вычисления направления:
BlockCocoa.java:
public void onBlockPlacedBy(World p_149689_1_, int p_149689_2_, int p_149689_3_, int p_149689_4_, EntityLivingBase p_149689_5_, ItemStack p_149689_6_)
{
    int l = ((MathHelper.floor_double((double)(p_149689_5_.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3) + 0) % 4;
    // WTF?
    p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, l, 2);
}

Короче, вот что меня интересует:
  1. Чзх творится с метадатой?
  2. Как метадата синхронизируется с клиентом?
  3. Должен ли я заботиться о сохранении меты в NBT?
 
Решение
1. Есть класс Direction, в нём есть массив directionToFacing как раз с этими значениями:
1577785743609.png
Используется он в в повторителе для каких-то вычислений с силой сигнала редстоуна, не вникал.
2. С помощью метода World#setBlockMetadataWithNotify. Последний параметр у него - флаг. В жавадоке написано какое значение что делает.
3. Нет. Нет. Нет. Ты сделал какуе-то дичь. Метадата и так всегда сама синхронится и сохраняется. Но может хранить значение от 0 до 15(как раз для поворотов идеально помещается). Если у тебя переменная больше - вообще не юзай метадату, а создай отдельную в тайле. Вот тут уже да, надо самому синхронить и сохранять.

tox1cozZ

aka Agravaine
8,455
598
2,892
1. Есть класс Direction, в нём есть массив directionToFacing как раз с этими значениями:
1577785743609.png
Используется он в в повторителе для каких-то вычислений с силой сигнала редстоуна, не вникал.
2. С помощью метода World#setBlockMetadataWithNotify. Последний параметр у него - флаг. В жавадоке написано какое значение что делает.
3. Нет. Нет. Нет. Ты сделал какуе-то дичь. Метадата и так всегда сама синхронится и сохраняется. Но может хранить значение от 0 до 15(как раз для поворотов идеально помещается). Если у тебя переменная больше - вообще не юзай метадату, а создай отдельную в тайле. Вот тут уже да, надо самому синхронить и сохранять.
 
1,159
38
544
Спасибо @Agravaine :j за ответ. Однако хотелось бы больше инфы про значения меты 0 и 1.
P.S. Как-то стремно этот массив построен. Легко получать direction не выходит.
 
Сверху