Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Скрыть объявление

BlockState /

Тема в разделе "Разработка плагинов для новичков", создана пользователем molor, 11 мар 2017.

Статус темы:
Закрыта.
  1. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Ну такое. Игрок может сломать сундук с вещами внутри. Перед разрушением блока я отменяю это событие, получаю BlockState блока сундука и сохраняю его в HashMap<Location, BlockState>, где Location - его координаты на сервере. Через несколько минут этот блок восстанавливается по этим данным. Всё бы хорошо, но.. все вещи в инвентаре сундука просто исчезают. Подскажите, какого чёрта? Чего я не знаю или что делаю неправильно?

    Добавление:
    Код:
    Location location = block.getLocation();
    
    if (hashMap.containsKey(location)) {
      return;
    }
    
    hashMap.put(location, block.getState());
    Восстановление:
    Код:
    ((InventoryHolder) block.getState()).getInventory().setContents(((InventoryHolder) hashMap.get(location)).getInventory().getContents());
     
  2. Хостинг MineCraft
    <
  3. 0x1EE7C0DE

    0x1EE7C0DE Участник Пользователь

    Баллы:
    36
    Сохраняй в мапу не BlockState, а сразу лист\массив айтемстаков из содержимого сундука
     
  4. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Проблема в том, что я планирую расширить код, добавив поддержку других блоков. Например, табличек. Насколько я понял, у всех этих блоков используется BlockState. И сейчас мне больше интересно, почему такой вариант не работает. Часа два убил на это, меняя по строчке, но ни к чему так и не пришёл.
     
  5. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Забавно, что в событии разрушения блока ((InventoryHolder) blockState).getInventory().getContents(); возвращает всё правильно, однако если вызвать этот же код позже через scheduler, то getContents() возвращает одни null'ы..

    Не врубаюсь, это как?
     
  6. 0x1EE7C0DE

    0x1EE7C0DE Участник Пользователь

    Баллы:
    36
    Может, блока на месте нет, когда нуллы идут?
     
  7. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Да, его там нет. Я взял с него BlockState (который, как пишут в доках, represents a captured state of a block, which will not change automatically), после чего Material у блока заменил на AIR. Спустя некоторое время я хочу восстановить этот блок со всеми его данными из BlockState, который просто хранится в HashMap, но получается вот такое.
     
  8. xDark

    xDark Активный участник Пользователь

    Баллы:
    96
    Skype:
    ailyashevich
    Имя в Minecraft:
    xDark
    дело в том что у блока не может быть контейнера т.е. инвентаря и т.д, НО у ентити - может. поэтому вместо того, чтобы получать блок тебе нужно получить TileEntity (TileEntityChest), как @alexandrage сказал уже выше
     
  9. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Я правильно понимаю, что это уже NMS и универсальности для любого типа блока и версии ядра не выйдет..? Или, как получить TileEntity иначе?
     
    Последнее редактирование: 11 мар 2017
  10. GoodCoder

    GoodCoder Активный участник Пользователь

    Баллы:
    76
    1. Получить TileEntity сундука.
    2. Сохранить его NBT в переменную
    3. Восстановить блок
    4. Загрузить NBT из переменной.

    Именно так работает сохранение в майне, в тех же модах, которые перемещают сундуки.
     
  11. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Так получать-то хоть?
    Код:
    CraftWorld craftWorld = (CraftWorld) location.getWorld();
    TileEntity tileEntity = craftWorld.getTileEntityAt(location.getBlockX(), location.getBlockY(), location.getBlockZ());
    
    if (tileEntity != null) {
      NBTTagCompound nbt = new NBTTagCompound();
      tileEntity.save(nbt);
    }
    А вот как записать эти данные в блок, я не пойму. Напишите пример кода, пожалуйста.
     
  12. GoodCoder

    GoodCoder Активный участник Пользователь

    Баллы:
    76
    tileEntity.read(nbt);
     
  13. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    хм, Spigot 1.11.2, The method read(NBTTagCompound) is undefined for the type TileEntity
     
  14. alexandrage

    alexandrage Администратор

    Баллы:
    173
    Skype:
    alexandr0116
    Ору с нубов. Через ведроапи же можно получить контейнер обычного сундука.
     
  15. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Так Вы хоть намёк дайте, в сторону какого метода рыть. Нубы ведь после прочтения Ваших мыслей нубами быть не перестанут. Наверное.

    Да и теперь уже нужен способ сохранения любого блока в память, а не только контейнер сундука. Но до меня вот не доходит, как это сделать лучше всего, поэтому я пробую всё подряд.
     
  16. xDark

    xDark Активный участник Пользователь

    Баллы:
    96
    Skype:
    ailyashevich
    Имя в Minecraft:
    xDark
    а точн Chest chest = (Chest) state;
     
  17. alexandrage

    alexandrage Администратор

    Баллы:
    173
    Skype:
    alexandr0116
    Код:
            BlockState state = block.getState();
            if(!(state instanceof InventoryHolder)) return;
            InventoryHolder chest = (InventoryHolder)state;
            if(chest instanceof Chest) {
                ItemStack[] stacks = chest.getInventory().getContents().clone();
            }
     
  18. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Нет, save.
    Просто клонируй BlockState/его содержимое себе и все дела.
     
  19. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Как? У BlockState нет clone(). Хотя этот метод и не должен быть, так как BlockState хранит в себе состояние блока в конкретный момент времени, и это сохранение не должно меняться. Однако, оно таки меняется.
     
  20. alexandrage

    alexandrage Администратор

    Баллы:
    173
    Skype:
    alexandr0116
    Забей, ответ постом выше.[DOUBLEPOST=1489346160,1489346111][/DOUBLEPOST]Ну а восстановить так chest.getInventory().setContents(stacks);
     
  21. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Да, знаю. Но повторюсь, нужен код, поддерживающий внутренние данные любого блока..
     
Статус темы:
Закрыта.

Поделиться этой страницей