1. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Помогите Получить инвентарь после его изменения

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

  1. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    Всем привет!
    Продолжаю делать верстаки. Более-менее функционал сделал, теперь надо наладить взаимодействие игрока с верстаком. Сейчас все это делаю через InventoryClickEvent, только вот он берёт инвентарь, который был до клика (когда игрок ещё не положил предмет), а делать какую-то кнопку для проверки рецепта не хочу.
    В общем как получить инвентарь, после того, как игрок положит/вытащит в/из него предмет?

    AdminInvMap AM = new AdminInvMap(); //Мапа <Player, AdminInventory> хранит открытые инвентари админов
    UserInventory UM = new UserInventory(); //Мапа <Player, UserInventory> хранит открытые инвентари игроков

    @EventHandler
    public void invClick(InventoryClickEvent e){
    if(e.getClickedInventory == null) return;
    Inventory i = e.getClickedInventory();
    Player p = (Player) e.getWhoClicked();


    //Чтобы игрок не мог шифтом перекинуть предметы в верстак
    if((UM.contKey(p)|| AM.contKey(p))&&e.getClickedInventory() == p.getInventory()&&e.isShiftClick()){
    e.setCancelled(true);
    return;
    }

    //Если у игрока открыт пользовательский верстак
    if(UM.contKey(p)){
    //Если ткнул именно в пользовательский верстак
    if(i == UM.getInventory();{
    if(Это не спец. слот){ //Если это чёрное стекло
    e.setCancelled(true); return;
    }

    if(Это слот матрицы){
    if(e.getCursor().getType() == Material.AIR && i.getItem(slot) == null) return; //Если курсор и слот пустые
    if(есть рецепт){
    if(уровень верстака >= уровень рецепта){
    i.setItem(resultSlot, result);
    }
    }
    }
    }
    }

    На первой картинке рецепт, который сделал админ. На второй - верстак игрока. Нужно делать лишнее действие (положил третий рычаг, чтобы проверка прошла)
     

    Вложения:

    Последнее редактирование: 4 апр 2021
  2. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    Так все теми же кликами
     
  3. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    https://disk.yandex.ru/d/0UcrLVRq-96deA
    У меня работает как я описал выше.
    На видео после "Текущий верстак" указывается размер матрицы крафта, пустые строки и столбцы удаляются. Ну как видно значения передаются с запозданием: когда в матрицу кладу третью слезу, размер равен 2 (но должен быть 3)
    Для обрезки я передаю в конструктор инвентарь из события
     
  4. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    https://disk.yandex.ru/i/ZVgZzgAC2zU8AA
    Заметил ещё одну особенность. Когда я нажимаю по нужной мне матрице, событие выполняется правильно, но лишь частично. В чате появляется сообщение "Дошло", но в коде я указал класть слиток железа в слот №0 после этого "Дошло". Но он появляется, только если я ткну в другое место, где по проверкам до вызова этого слитка не доходит.
    Мне нужна помощь
     
  5. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    Ещё хочу знать как проверить, что игрок заполнил слоты с помощью зажатого ПКМ
     
  6. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    Событие клика происходит до, непосредственно, факта установки предмета. Проще всего будет учесть предмет вручную при поиске рецепта, либо подождать тик.
     
  7. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    Ну в ручную у меня не получилось. А вот с задержкой идея была, но я ни разу с BukkitRunnable не работал. Можете дать пример задержки?
     
  8. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    PHP:
    Bukkit.getScheduler().runTaskLater(plugin, () -> {
        
    // todo
    }, 1);
    plugin - экземпляр твоего плагина.
     
  9. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    Возможно я что-то не так делаю, но при попытке сделать новый инвентарь и задать ему значение clickedInventory IDE ругается, что этот инвентарь должен быть final и обязательно массивом. Ну и в консоль бьёт ошибки
    PHP:
    final Inventory[] chek = new Inventory[1];
                        
    Bukkit.getScheduler().runTaskLater(Main.plugin, () -> {
                            
    chek[0] = e.getClickedInventory();}, 1);
     
  10. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    А тебе вроде и не нужно создавать новую переменную под него - используй тот же i.
     
  11. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    Ага. Опять попросило переделать его в массив инвентарей. Переделал, ошибок нет, но всё равно запоздание на клик осталось. Или все действия с проверкой крафта надо делать непосредственно внутри шедулера? Просто сейчас я пытался переопределить в нем инвентарь, а проверка идёт после вне него
     
  12. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    Да, надо внутри было сделать.
     
  13. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    Все тот же клик ивент.
     
  14. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    Ну так клик ивент идет до изменения, что и логично. Тебе нужно добавить курент айтем еще, с него же и номер слота получишь куда помещается новый предмет.
     
  15. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    Как то так
    Inventory inv = e.getClickedInventory();
    ...
    List<ItemStack> list = Arrays.asList(inv.getContents());
    list.add(e.getSlot(), e.getCurrentItem());
    Ну а потом уже сравнивать свои списки.
    Это грубый пример конечно, если нужно учитывать число предметов, придется еще сложить, если одинаковые. И это еще без учета перемещения с шифтом, там логика будет уже другой и нужно будет самому уже просчитывать куда должен попасть новый предмет..
     
    Последнее редактирование: 5 апр 2021
  16. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    Мне понравился вариант с задержкой, который дал imDaniX.
    А вот заполнение инвентаря с зажатым ПКМ не считается кликом. По крайней мере сообщение, указанное сразу при совершении события, не посылается игроку
     
  17. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    Это не безопасно. 50мс это достаточно большой интервал.
     
    Последнее редактирование: 6 апр 2021
  18. alexandrage

    alexandrage Старожил Пользователь

    Баллы:
    173
    Так это уже другой ивент InventoryDragEvent
     
  19. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    Сделал через "клонирование" инвентаря из события. Клон имеет то же значение как инвентарь после события клика. Проверка на наличие крафта проходит, а вот e.getClickedInventory().setItem(resultSlot, resultItem) внутри проверки не выполняется, до тех пор пока игрок не тыкнет куда угодно кроме рабочей зоны (матрицы) верстака. Как это пофиксить?
     
  20. Автор темы
    ToBlEzZ

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

    Баллы:
    76
    Хотя в инвентарь не устанавливается предмет, даже если тыкнуть по нему
     

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