Listener не распознает нажатие

scrimers

Premium
Сообщения
37
1.12.2
Хотел сделать чтоб при нажатии пкм спец мечом выдавал скорость, ошибок нету!
По возможности распишите почему такое происходит

Java:
public class Handler implements Listener{
    @EventHandler
    public void use(PlayerInteractEvent e) {
        if(e.getAction() != Action.RIGHT_CLICK_AIR && e.getAction() != Action.RIGHT_CLICK_BLOCK) return;
        if(e.getPlayer().getInventory().getItemInMainHand().getType() !=Material.IRON_SWORD) return;
        Player p = e.getPlayer();
        ItemStack item = p.getInventory().getItemInMainHand();
                if(item.getItemMeta().hasDisplayName()) return;
                if(item.getItemMeta().hasLore()) return;
                if(item.getItemMeta().getDisplayName().equals(ChatColor.GOLD +"Muramasa"))return;
                if(item.getItemMeta().getLore().get(0).contentEquals(ChatColor.WHITE +"Лезвие впитывает в себя всю кровь врагов"))return;
              
                e.setCancelled(true);
        p.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,1 ,20));
        p.playSound(p.getLocation(), Sound.ENTITY_FIREWORK_LAUNCH, 8, 3);
      
      
    }
}
-----------------
  private void regCraftMU() {
      
         NamespacedKey m = new NamespacedKey(this, "MURAMASA");
         ItemStack item = new ItemStack(Material.IRON_SWORD);
         item.setItemMeta(null);
      
         ItemMeta meta = item.getItemMeta();
         meta.setDisplayName(ChatColor.GOLD +"Muramasa");
         meta.addEnchant(Enchantment.DAMAGE_ALL, 8, true);

         List<String> lore = new ArrayList<String>();
         lore.add(ChatColor.WHITE +"Лезвие впитывает в себя всю кровь врагов");
         lore.add(ChatColor.GOLD +"CLASS C ");
         meta.setLore(lore);
         item.setItemMeta(meta);
      
         ShapedRecipe mu = new ShapedRecipe(m, item);
         mu.shape("IDI", "VSV", "IDI");
         mu.setIngredient('I', Material.IRON_INGOT);
         mu.setIngredient('D', Material.DIAMOND);
         mu.setIngredient('S', Material.IRON_SWORD);
         mu.setIngredient('V', Material.LAVA_BUCKET);
         Bukkit.addRecipe(mu);
    }
 
Решение
Java:
public class Handler implements Listener{

    @EventHandler

    public void use(PlayerInteractEvent e) {
        Player p = e.getPlayer;
        if(e.getAction() == Action.RIGHT_CLICK_AIR) {
            if (p.getInventory().getItemInMainHand().getItemMeta().getDisplayName().equals(ChatColor.GOLD +"Muramasa")) {
                p.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,1 ,20));
                p.playSound(p.getLocation(), Sound.ENTITY_FIREWORK_LAUNCH, 8, 3);
            }
        }
    }

Я бы сделал так. Можно ешё добавить проверку на наличие меты, но лично у меня такая структура в консоль ошибок не выводила. У тебя есть строка "if(item.getItemMeta().getDisplayName().equals(ChatColor.GOLD +"Muramasa"))return;"...
Раз первую проверку не проходит, значит механика меча так сделана, что ПКМ не работает, как мне кажется.
Объединено

Может быть, вот так будет работать? Не уверен :unsure:

Java:
Material itemInHand = player.getInventory().getItemInMainHand().getType();
Action action = e.getAction();
if ((action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) && User.isAlive(player)
        && itemInHand == Material.IRON_SWORD) {
    while (player.isBlocking() || player.isHandRaised()) {
        //Действия
    }
}
 
Последнее редактирование:
Java:
public class Handler implements Listener{

    @EventHandler

    public void use(PlayerInteractEvent e) {
        Player p = e.getPlayer;
        if(e.getAction() == Action.RIGHT_CLICK_AIR) {
            if (p.getInventory().getItemInMainHand().getItemMeta().getDisplayName().equals(ChatColor.GOLD +"Muramasa")) {
                p.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,1 ,20));
                p.playSound(p.getLocation(), Sound.ENTITY_FIREWORK_LAUNCH, 8, 3);
            }
        }
    }

Я бы сделал так. Можно ешё добавить проверку на наличие меты, но лично у меня такая структура в консоль ошибок не выводила. У тебя есть строка "if(item.getItemMeta().getDisplayName().equals(ChatColor.GOLD +"Muramasa"))return;". Зачем она? Если у игрока в руках нужный меч, она просто завершает код. Зачем столько return?
Имея в руках такой меч, у тебя return срабатывает до того, как исполняется код эффектов. Естественно ошибок нет, ведь написано правильно.
Объединено

Зачем делать тысячу проверок вместо одного if? Если тебе нужно найти среди пяти чашек красную, ты будешь писать проверку на каждый из существующих цветов или просто на красный?
Объединено

Java:
public class Handler implements Listener{

    @EventHandler
    public void use(PlayerInteractEvent e) {
        Player p = e.getPlayer;
        if(e.getAction() == Action.RIGHT_CLICK_AIR) {
            if (p.getInventory().getItemInMainHand() == null) return;
            if (!p.getInventory().getItemInMainHand().hasItemMeta()) return;
            if (p.getInventory().getItemInMainHand().getItemMeta().getDisplayName().equals(ChatColor.GOLD +"Muramasa")) {
                p.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,1 ,20));
                p.playSound(p.getLocation(), Sound.ENTITY_FIREWORK_LAUNCH, 8, 3);
            }
        }
    }

Более правильная версия в плане проверок
 
Последнее редактирование:
У тебя есть строка "if(item.getItemMeta().getDisplayName().equals(ChatColor.GOLD +"Muramasa"))return;". Зачем она? Если у игрока в руках нужный меч, она просто завершает код
Это верно, скорее, в этом и ошибка.
По поводу сравнения: как предлагалось на форуме ранее, можно закешериовать айтемстак и потом сравнивать когда нужно.
 
Это верно, скорее, в этом и ошибка.
По поводу сравнения: как предлагалось на форуме ранее, можно закешериовать айтемстак и потом сравнивать когда нужно.
[OFFTOPIC]Можно ссылку на кэширование айтемстака? Не видел такого, интересно глянуть[/OFFTOPIC]
 
[OFFTOPIC]Не могу сказать точно, правильно ли это названо было кешированием, однако все "кеширование" заключается в этом:

Java:
public class ItemStackList {
    public static ItemStack firstItemStack = awesomeSword();

    public static ItemStack awesomeSword() {
        return new ItemStack(Material.DIAMOND_SWORD);
    }
}
//...
if (event.getItemInMainHand().equals(ItemStackList.firstItemStack)) {
    event.getItemInMainHand().setType(Material.DIRT);
}
[/OFFTOPIC]
 
Не могу сказать точно, правильно ли это названо было кешированием, однако все "кеширование" заключается в этом:
[OFFTOPIC]Спустя столько лет... А айтемстак будет доступен из любого класса или он внутренний?[/OFFTOPIC]
(хотел выпендреться)
Делай поменьше проверок на действия) Двух моих хватает
 
[OFFTOPIC]Почему нехорошо? Я вчера расписывал плагин один, там было много промежуточных предметов и проверок на их наличие. И приходилось копировать код итемстака, грубо говоря, и на выдачу, и на изымание. А с такой штукой можно в одном классе все предметы задать и не копипастить лишний раз, разве нет?[/OFFTOPIC]
 
[OFFTOPIC]Вряд ли кому то есть дело до того чтобы взять и испортить твой плагин, но вообще это как бы не безопасно. Допустим, в нашей программе есть класс Car...
Код:
public class CarList {
    public static Car car = new Car();
    public static Car car2 = new Car();
}
//...
CarList.car = какой-то_другой_объект_машины
CarList.car2 = null;
//...
if (event.getCar().equals(CarList.car2)) { // тут начнутся проблемы, например, совершенно другое поведение программы

}
[/OFFTOPIC]
 
[OFFTOPIC]Инкапсуляция это верно. Однако... Смотри, вернемся к предметам. У нас есть несколько листенеров: PlayerListener, EntityListener и другие. Это разделение удобно, потому что в первом мы прослушиваем игрока, во втором всех сущностей, и так далее. Если нам нужно сравнить предметы в каждом из этих листенеров, а перед этим расписать их в начале класса - получается опять копипаста. Мы можем использовать private static поля в классе ItemStackList и получать предметы с помощью геттеров, но это опять таки удобно только если у тебя не полсотни предметов. Я столкнулся с такой же проблемой в конфигурациях, и в итоге слепил свою реализацию конфигов. Вообще, одним из возможных решений является public static final модификаторы, но они тоже не всегда могут быть удобными.[/OFFTOPIC]
 
[OFFTOPIC]Спасибо, буду смотреть. Что-то не додумался, что так вообще можно. У меня просто в одном классе один и тот же предмет 3 раза скопипастен, если нужно будет что-то поменять - придётся искать каждую пасту и менять. Посмотрю, в общем. Спасибо.[/OFFTOPIC]
 
Назад
Сверху Снизу