Применение NBT в предмете

216
6
19
Очередной перевод зарубежного урока от менья.
На этот раз статья была взята с оф. вики форджа.

Условия для понимания туториала:
  1. Знать основы Java
  2. Иметь представление о создании предметов
  3. Иметь немного свободного места в голове, чтобы запомнить написанное ниже

Информация, представленная в уроке проверенна на версию 1.7.10.
В версиях выше могут измениться названия методов.
Распространенная ошибка начинающих программистов - помещение, изменяемой в процессе игры, переменной в начале класса предмета. Это делать неправильно, т.к. каждый предмет создается и вызывается единожды. "Шо ты несешь?!". Предположим, у вас есть палочка, которая кастует заклинание и на кнопку F вы хотите сменить заклинание. Если ваша переменная с заклинанием помещена в начале класса предмета, то при нажатии кнопки, заклинание сменится у всех на сервере. Неплохо, правда? Не совсем... Как раз таки NBT дает возможность иметь разные заклинания на разных палочках.
NBT может содержать в себе множество базов типов данных. Так же он поддерживает некоторые структуры данных (например, List). NBT предмета - это NBTTagCompound, которое данные в HashMap в базе данных.
В этом примере мы сделаем предмет-ключ, который будет открывать дверь, если коды двери и предмета сходятся. Мы разберем только то, как в нашем случае надо работать в NBT в классе двери и в предмете.

Мы рассмотрим некоторые методы, которые взаимодействуют с NBT. Не буду перечислять все методы, их можно увидеть в классе net.minecraft.item.Item. Там вы увидите описание для каждого интересующего вас метода.

Вызывается, когда предмет используют (на ПКМ), возвращает true, если что-то происходит, false - если ничего не происходит.
Код:
public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
Вызывается каждый тик (20 раз в секунду), пока предмет в инвентаре игрока.
Код:
public void onUpdate(ItemStack par1ItemStack, World par2World, Entity par3Entity, int par4, boolean par5) {}
Вызывается, когда предмет создается (крафтится, выплавляется).
Код:
   public void onCreated(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer) {}
Вызывается, когда игрок отпускает кнопку использования предмета. Аргументы: itemstack, world, entityplayer, itemInUseCount
Код:
   public void onPlayerStoppedUsing(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer, int par4) {}
Добавляет строки к описанию предмета (описание предмета высвечивается, когда наводишь на предмет в инвентаре).
Код:
   public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4) {}
ItemNbtStatStaff.png
Возвращает true, если игрок может взаимодействовать с миром (например, ставить блоки) с помощью предмета и false - если наоборот.
Код:
public boolean canItemEditBlocks()
Вызывается, когда предмет начинают использовать (но перед тем, как что-либо происходит).
  • @param stack - Стак предмета
  • @param player - Игрок, который использует предмет
  • @param world - Нынешний мир
  • @param x - Позиция X
  • @param y - Позиция Y
  • @param z - Позиция Z
  • @param side - Сторона
  • @return - Напишите return true для предотвращения любой обработки
Код:
public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ)
Теперь для нашего дверного ключа нам нужно генерировать каждый раз новый ключ при создании самого предмета.
Код:
public void onCreated(ItemStack itemStack, World world, EntityPlayer player)
{
itemStack.stackTagCompound = new NBTTagCompound();
}
Создаем NBT соединение выше.

Теперь нам нужно добавить пару строк в onCreate()
Код:
itemStack.stackTagCompound.setString("owner", player.username); itemStack.stackTagCompound.setInteger("code", (int)(Math.random*Integer.MAX_VALUE));
Мы добавили 2 NBT характеристики предмету - ключ и владелец.

Теперь давайте отобразим эту информацию в описании, для наглядности.
Код:
public void addInformation(ItemStack itemStack, EntityPlayer player, List list, boolean par4) {
    if (itemStack.stackTagCompound != null) {
       String owner = itemStack.stackTagCompound.getString("owner");
       int code = itemStack.stackTagCompound.getInteger("code");
       list.add("owner: " + owner);

       if (owner.equals(player.username)) {
           list.add(EnumChatFormatting.GREEN + "code: " + code);
       } else {
           list.add(EnumChatFormatting.RED + "code: " + EnumChatFormatting.OBFUSCATED + code);
       }
    }
}
Проверка на null, очень важна, ибо метод onCreated вызывается один раз - при создании. И если вы предмет не создавали, значит у нашего дверного ключа нет ключа (да-да, тавтология). Далее мы проверяем, что дверной ключ, который игрок держит в руках, создам им, то делаем ключ зеленого цвета, в ином случае - красного с помощью EnumChatFormatitng.
Выглядит это так:
ItemNbtKey.png
ItemNbtObfuscatedKey.png
Теперь нужно создать метод, который будет вызываться из onBlockActivated, для проверки вашего ключа в классе вашей двери.
Код:
public static void int getCodeIfValid(EntityPlayer player){

   ItemStack hold = player.inventory.getCurrentItem();
   if(hold.itemID != MainMod.key.itemID){
       return -1;
   }
   if(!hold.stackTagCompound.getString("owner").equals(player.username)){
       return -1;
   }
   return hold.stackTagCompound.getInteger("code");
}
А вот сам метод onBlockActivated()
Код:
onBlockActivated(args){

   if(ItemKey.getCodeIfValid(player) == ((TileEntityLockedDoor)world.getBlockTileEntity(x, y, z)).code){
       //код открытия двери
   }
}
Да.. В этом туториале я не учел некоторые аспекты, к примеру, зачем игроку ключ, если он может открыть дверь рукой? Я хотел сделать пример использования NBT, а не разъяснения на тему создания мода на ключи. Воспользовавшись моим уроков вы можете сделать свой мод.
 
Последнее редактирование:
"Шо ты несешь?!"

Это пересылка своих пакетов я правильно понял ?
А то что то он не понятно расписал.


PS: А в 1.6.4 нет writeToNBT ?
 
7,099
324
1,510
НБТ - способ хранения данных.
 
Сверху