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

  • Автор темы Автор темы 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);
}
}
}
}
}

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

Вложения

  • javaw_4Kred8QntR.png
    javaw_4Kred8QntR.png
    29,3 КБ · Просмотры: 18
  • изображение_2021-04-04_104621.png
    изображение_2021-04-04_104621.png
    5,6 КБ · Просмотры: 16
Последнее редактирование:
https://disk.yandex.ru/d/0UcrLVRq-96deA
У меня работает как я описал выше.
На видео после "Текущий верстак" указывается размер матрицы крафта, пустые строки и столбцы удаляются. Ну как видно значения передаются с запозданием: когда в матрицу кладу третью слезу, размер равен 2 (но должен быть 3)
Для обрезки я передаю в конструктор инвентарь из события
 
https://disk.yandex.ru/i/ZVgZzgAC2zU8AA
Заметил ещё одну особенность. Когда я нажимаю по нужной мне матрице, событие выполняется правильно, но лишь частично. В чате появляется сообщение "Дошло", но в коде я указал класть слиток железа в слот №0 после этого "Дошло". Но он появляется, только если я ткну в другое место, где по проверкам до вызова этого слитка не доходит.
Мне нужна помощь
 
Ещё хочу знать как проверить, что игрок заполнил слоты с помощью зажатого ПКМ
 
Событие клика происходит до, непосредственно, факта установки предмета. Проще всего будет учесть предмет вручную при поиске рецепта, либо подождать тик.
 
Событие клика происходит до, непосредственно, факта установки предмета. Проще всего будет учесть предмет вручную при поиске рецепта, либо подождать тик.
Ну в ручную у меня не получилось. А вот с задержкой идея была, но я ни разу с BukkitRunnable не работал. Можете дать пример задержки?
 
Ну в ручную у меня не получилось. А вот с задержкой идея была, но я ни разу с BukkitRunnable не работал. Можете дать пример задержки?
PHP:
Bukkit.getScheduler().runTaskLater(plugin, () -> {
    // todo
}, 1);
plugin - экземпляр твоего плагина.
 
PHP:
Bukkit.getScheduler().runTaskLater(plugin, () -> {
    // todo
}, 1);
plugin - экземпляр твоего плагина.
Возможно я что-то не так делаю, но при попытке сделать новый инвентарь и задать ему значение clickedInventory IDE ругается, что этот инвентарь должен быть final и обязательно массивом. Ну и в консоль бьёт ошибки
PHP:
final Inventory[] chek = new Inventory[1];
                    Bukkit.getScheduler().runTaskLater(Main.plugin, () -> {
                        chek[0] = e.getClickedInventory();}, 1);
 
Возможно я что-то не так делаю, но при попытке сделать новый инвентарь и задать ему значение clickedInventory IDE ругается, что этот инвентарь должен быть final и обязательно массивом. Ну и в консоль бьёт ошибки
PHP:
final Inventory[] chek = new Inventory[1];
                    Bukkit.getScheduler().runTaskLater(Main.plugin, () -> {
                        chek[0] = e.getClickedInventory();}, 1);
А тебе вроде и не нужно создавать новую переменную под него - используй тот же i.
 
А тебе вроде и не нужно создавать новую переменную под него - используй тот же i.
Ага. Опять попросило переделать его в массив инвентарей. Переделал, ошибок нет, но всё равно запоздание на клик осталось. Или все действия с проверкой крафта надо делать непосредственно внутри шедулера? Просто сейчас я пытался переопределить в нем инвентарь, а проверка идёт после вне него
 
Ага. Опять попросило переделать его в массив инвентарей. Переделал, ошибок нет, но всё равно запоздание на клик осталось. Или все действия с проверкой крафта надо делать непосредственно внутри шедулера? Просто сейчас я пытался переопределить в нем инвентарь, а проверка идёт после вне него
Да, надо внутри было сделать.
 
https://disk.yandex.ru/d/0UcrLVRq-96deA
У меня работает как я описал выше.
На видео после "Текущий верстак" указывается размер матрицы крафта, пустые строки и столбцы удаляются. Ну как видно значения передаются с запозданием: когда в матрицу кладу третью слезу, размер равен 2 (но должен быть 3)
Для обрезки я передаю в конструктор инвентарь из события
Ну так клик ивент идет до изменения, что и логично. Тебе нужно добавить курент айтем еще, с него же и номер слота получишь куда помещается новый предмет.
 
Как то так
Inventory inv = e.getClickedInventory();
...
List<ItemStack> list = Arrays.asList(inv.getContents());
list.add(e.getSlot(), e.getCurrentItem());
Ну а потом уже сравнивать свои списки.
Это грубый пример конечно, если нужно учитывать число предметов, придется еще сложить, если одинаковые. И это еще без учета перемещения с шифтом, там логика будет уже другой и нужно будет самому уже просчитывать куда должен попасть новый предмет..
 
Последнее редактирование:
Как то так
Inventory inv = e.getClickedInventory();
...
List<ItemStack> list = Arrays.asList(inv.getContents());
list.add(e.getSlot(), e.getCurrentItem());
Ну а потом уже сравнивать свои списки.
Это грубый пример конечно, если нужно учитывать число предметов, придется еще сложить, если одинаковые. И это еще без учета перемещения с шифтом, там логика будет уже другой и нужно будет самому уже просчитывать куда должен попасть новый предмет..
Мне понравился вариант с задержкой, который дал imDaniX.
А вот заполнение инвентаря с зажатым ПКМ не считается кликом. По крайней мере сообщение, указанное сразу при совершении события, не посылается игроку
 
Это не безопасно. 50мс это достаточно большой интервал.
Сделал через "клонирование" инвентаря из события. Клон имеет то же значение как инвентарь после события клика. Проверка на наличие крафта проходит, а вот e.getClickedInventory().setItem(resultSlot, resultItem) внутри проверки не выполняется, до тех пор пока игрок не тыкнет куда угодно кроме рабочей зоны (матрицы) верстака. Как это пофиксить?
 
Хотя в инвентарь не устанавливается предмет, даже если тыкнуть по нему
 
Назад
Верх