Возвращение меты поворота и роста

Версия Minecraft
1.12.2
5,018
47
783
Здравствуйте! В общем, имеется некий блок, у которого есть два стейта - один инт - стадия роста, а другой EnumAxis. Собственно говоря, мне необходимо чтобы в мету нормально сохранялось и поворот, и мета роста. Но в мете можно вернуть только одно значение.

И вот никак у меня в голове не укладывается, как можно увязать и сохранить в мету обе переменных.
На данный момент у меня только дефолтный метод, который сохраняет лишь мету поворота... Сижу уже полдня над такой фигней, никак не придумаю.
Java:
public int getMetaFromState(IBlockState state)
    {
        int meta = 0;
        EnumFacing.Axis axis = (EnumFacing.Axis)state.getValue(AXIS);
       
       
        if (axis == EnumFacing.Axis.X)
        {
            meta |= 4;
        }
        else if (axis == EnumFacing.Axis.Z)
        {
            meta |= 8;
            return meta;
        }
        return meta;
    }

Вот как наоборот получить - я понял, а сохранить...

Java:
    public IBlockState getStateFromMeta(int meta)
    {
        EnumFacing.Axis enumfacing$axis = EnumFacing.Axis.Y;
    
        
        int i = meta & 12;

        if (i == 4)
        {
            enumfacing$axis = EnumFacing.Axis.X;
        }
        else if (i == 8)
        {
            enumfacing$axis = EnumFacing.Axis.Z;
        }

        return (this.getDefaultState().withProperty(AXIS, enumfacing$axis).withProperty(STAGE, meta));
    }
 
Решение
Изначально ты суешь мету которую хранит твой блок
BitsArray bits = new BitsArray(meta);

далее получаешь свои значения двух переменных:
Java:
int rotateAngle = bits.GetInt(1,2, 0); //0,1,2,3 * 90
int growth = bits.GetInt(3,6, 2);
GetInt(1,2,0)
взять число лежащим по биту с 1 до 2 бита, где 0 - это сколько из 8 бит нужно удалить справа (удалить с самого начала)
поворот у тебя имеет 4 значения (вторые числа - это в виде двоичной):
0 = 00
1 = 01
2 = 10
3 = 11
это чтоб тебе понятнее было, разберем вторую строку
int growth = bits.GetInt(3,6, 2);
Взять число начиная с 3го бита по 6ой включительно, и удалить 2 бита справа (в массиве хранятся числа в 8ми битах), первые два бита будут чему то равны, потому что там у нас другое число...
5,018
47
783
Да бы хорошо... но там тип бревна, там класс где метадата есть, которая задается. А у меня число обычное, integer.
Если бы можно было, я б так давно сделал вот... meta = meta | ((Integer)state.getValue(STAGE)).getMetadata();
Но нету в интеджере никакой метадаты.В принципе каст там необязательный даже, но это для наглядности
 
5,018
47
783
Я нашел что то похожее в диоде... Но игра крашится с нуллом.
Java:
    public IBlockState getStateFromMeta(int meta)
    {
        return this.getDefaultState().withProperty(AXIS, EnumFacing.getFront(meta)).withProperty(STAGE, Integer.valueOf(1 + (meta >> 2)));
    }
    public int getMetaFromState(IBlockState state)
    {
        int meta = 0;
        meta = meta | ((EnumFacing)state.getValue(AXIS)).getIndex();
        meta = meta | ((Integer)state.getValue(STAGE)).intValue() - 1 << 2;
        return meta;
    }

Причем краш какой то очень странный. Не имеющий никакого отношения к блоку...
Но он точно из за этого.

Java:
[16:10:59] [main/FATAL] [FML]: The following problems were captured during this phase
[16:10:59] [main/ERROR] [FML]: Caught exception from realism (realism)
java.lang.ExceptionInInitializerError: null
    at com.legendgamer.realism.world.biomes.magmatic.MagmaticBiome.<init>(MagmaticBiome.java:28) ~[bin/:?]
    at com.legendgamer.realism.reg.RegBiomes.<clinit>(RegBiomes.java:17) ~[bin/:?]
    at com.legendgamer.realism.proxy.CommonProxy.preInit(CommonProxy.java:20) ~[bin/:?]
    at com.legendgamer.realism.proxy.ClientProxy.preInit(ClientProxy.java:31) ~[bin/:?]
    at com.legendgamer.realism.Realism.preInit(Realism.java:34) ~[bin/:?]
 
1,038
57
229
Всё просто друг мой.
Для поворота нужен 6 значений, число 6 в битах занимает 3 бита. Остальные БИТЫ ты можешь использовать для чего то ещё, их остается не так много, но может хватит для роста в том числе
4 бита - это уже 16 (от 0 до 15) значений.
System.out.println(Integer.toBinaryString(15));
 
5,018
47
783
Спасибо, за информацию. Но что мне это дает?
Мне трех значений вполне хватает, т.к поворот просто по трем осям.
 
2,505
81
397
Это тебе дает то, что на поворот у тебя 3 бита, и на стадию роста роста остается 1 бит (либо выросло, либо нет).
Но если тебе для поворота нужно только 4 состояния, то это 2 бита. И на стадии роста уже можно разгуляться.
 
5,018
47
783
поворота нужно только 4 состояния,
Так три же, а не 4. X ось, Y и Z. В таком случае сколько получается? Или так в принципе нельзя?

Вот в диоде каким то образом умещают енумфейсинг и инт

Java:
   i = i | ((EnumFacing)state.getValue(FACING)).getHorizontalIndex();
        i = i | ((Integer)state.getValue(DELAY)).intValue() - 1 << 2;
Я так понял этим <<2 два бита фейсинга сдвигаются в сторону освобождая ячейки еще двум битам инта. А те два которые были изначально от фейсинга куда сдвигаются то вообще?
 
5,018
47
783
Вот так сейчас код выглядит:

Java:
    public IBlockState getStateFromMeta(int meta)
    {
        EnumFacing.Axis enumfacing$axis = EnumFacing.Axis.Y;
   

        return (this.getDefaultState().withProperty(AXIS, enumfacing$axis).withProperty(STAGE, Integer.valueOf(1 + (meta >> 2))));
    }

   
    public int getMetaFromState(IBlockState state)
    {
    //    System.out.println("getMetaFromState " + state.getValue(AXIS));
        int meta = 0; //мета 0
        meta = meta | ((EnumFacing.Axis)state.getValue(AXIS)); //тут надо получить из осей каким то образом инт. Допустим это ordinal() можно сделать... или нельзя? 
       meta = meta | ((Integer)state.getValue(STAGE)).intValue() << 2;
        return meta;
   
       
       
    }
 
Последнее редактирование:
1,038
57
229
Код:
byte meta = 18;
BitsArray bits = new BitsArray(meta);
int rotateAngle = bits.GetInt(1,3); //0,1,2,3,4 * 90
int growth = bits.GetInt(4,7);
System.out.println("rotateAngle:" + rotateAngle);
System.out.println("growth:" + growth);

growth++;

BitsArray newbits = new BitsArray(Integer.toBinaryString(growth) + Integer.toBinaryString(rotateAngle));
meta = (byte)newbits.GetInt();
System.out.println("meta:" + meta);
ну а недостающий элемент тут ZZZubec/PluginUtils
специально для тебя написал ;)
 
5,018
47
783
Спасибо большое... А можешь теперь рассказать что тут происходит, пожалуйста? Я так ничерта и не понял...
И будет ли это с ванильными фейсингами и прочей лабудой работать?
Ты просто сделал кастомную мету? А она будет сохранятся в стейт? А будет она восприниматься майном?
Да и поворот .. это не не int, а EnumFacing.Axis который я пока даже не придумал как в инт перевести... если ток запарсить, но это парсер свой писать.
 
Последнее редактирование:
1,038
57
229
Блин, ошибки щас поправлю, погоди немного. Очень торопился..
 
5,018
47
783
Короче, я сгорел. Мне проще и быстрее создать еще один блок с фейсингами и назвать его ветки, чем мучаться этим говном. Спасибо, проблема решена.
 
1,038
57
229
Код:
System.out.println("-----------------------");
byte meta = 23;
BitsArray bits = new BitsArray(meta);
int rotateAngle = bits.GetInt(1,2, 0); //0,1,2,3 * 90
int growth = bits.GetInt(3,7, 2);
System.out.println("rotateAngle:" + rotateAngle);
System.out.println("growth:" + growth);

growth++;

BitsArray ba_growth = new BitsArray(growth);
BitsArray ba_rotate = new BitsArray(rotateAngle);
BitsArray result = BitsArray.join(ba_rotate, 2, ba_growth );
meta = (byte)result.GetInt();
System.out.println("meta:" + meta);
теперь пишу объяснение..
 
1,038
57
229
Изначально ты суешь мету которую хранит твой блок
BitsArray bits = new BitsArray(meta);

далее получаешь свои значения двух переменных:
Java:
int rotateAngle = bits.GetInt(1,2, 0); //0,1,2,3 * 90
int growth = bits.GetInt(3,6, 2);
GetInt(1,2,0)
взять число лежащим по биту с 1 до 2 бита, где 0 - это сколько из 8 бит нужно удалить справа (удалить с самого начала)
поворот у тебя имеет 4 значения (вторые числа - это в виде двоичной):
0 = 00
1 = 01
2 = 10
3 = 11
это чтоб тебе понятнее было, разберем вторую строку
int growth = bits.GetInt(3,6, 2);
Взять число начиная с 3го бита по 6ой включительно, и удалить 2 бита справа (в массиве хранятся числа в 8ми битах), первые два бита будут чему то равны, потому что там у нас другое число хранится. И эти 2а бита нам не нужны в этом числе.
второе число у нас занимает 4 бита (3ий бит, 4ый, 5ый, 6ой)

нам допустим надо увеличить рост, делаем
growth++;

теперь нам надо как то запихнуть это всё обратно

Java:
BitsArray ba_growth = new BitsArray(growth);
BitsArray ba_rotate = new BitsArray(rotateAngle);
BitsArray result = BitsArray.join(ba_rotate, 2, ba_growth );
meta = (byte)result.GetInt();

Создаем два обьекта, каждый из которых хранится и раскладывается в 8 битах
а потом соединяем первый, со вторым.
BitsArray.join(ba_rotate, 2, ba_growth );
число 2а, это длинна в битах первого числа. То есть записать второе число после 2го бита (то бишь начиная с 3го).

Пользуйся.. фух, писец меня тут отвлекали.
Не разберешься пиши в скайп или телеграмм, ну или тут. Просто там быстрее будет..
Пример написан вот прям то что тебе надо, ничего менять тебе не придется.
 
Последнее редактирование:
5,018
47
783
Я тут просто сделал второй блок уже. Но эта кастомная мета я думаю многим пригодится. А запили в туторах это. Чего мне то... пусть всем будет. А тут не найдет никто...
 
Сверху