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

Помогите [РЕШЕНО] Добавление зачарований в книгу через EnchantItemEvent

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

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

    GreenBudgie Ньюби Пользователь

    Баллы:
    1
    Мне нужно добавить собственный энчант в книгу при ее зачаровании. Пытаюсь сделать через EnchantItemEvent, но есть проблема. Майн меняет обычную книгу на зачарованную уже после срабатывания эвента, а поэтому не получается изменить EnchantmentStorageMeta. Был вариант создать поток и через несколько миллисекунд поменять EnchantmentStorageMeta у книги, но этот способ мне кажется не очень стабильным.
     
  2. Хостинг MineCraft
    <
  3. TheZefirrkka

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

    Баллы:
    76
    Skype:
    RomaMamkinHasker1337
    Имя в Minecraft:
    TheZefirrkka
  4. Автор темы
    GreenBudgie

    GreenBudgie Ньюби Пользователь

    Баллы:
    1
    Было бы странно, если бы я не сунулся сразу в гугл. Нет, ни на русскоязычных форумах, ни на иностранных прямого ответа я не нашел. Искал по сурсам разных плагинов на гитхабе, связанных с зачарами - но и там ничего не нашел (в этих плагинах все происходит через команды, а не через чарку).
     
  5. TheZefirrkka

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

    Баллы:
    76
    Skype:
    RomaMamkinHasker1337
    Имя в Minecraft:
    TheZefirrkka
    Месяц-два назад в этом разделе была про это тема... Плохо искал[DOUBLEPOST=1497537948,1497537915][/DOUBLEPOST]
    Почему?
     
  6. Автор темы
    GreenBudgie

    GreenBudgie Ньюби Пользователь

    Баллы:
    1
    Поиск не дает результатов. Можно ссылку?
    Если что-то будет происходить не моментально, то есть небольшой шанс того, что игрок уже закроет инвентарь по Esc и доп. зачар просто не успеет наложиться. Хотя потоки для меня еще не совсем понятны, но все же задержки - это нехорошо. Однако, если других вариантов не будет, то сделаю так.
     
  7. TheZefirrkka

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

    Баллы:
    76
    Skype:
    RomaMamkinHasker1337
    Имя в Minecraft:
    TheZefirrkka
    Так просто следай минимальную задержку, 1 тик, например.[DOUBLEPOST=1497538927,1497538894][/DOUBLEPOST]
    Тут поиск криво работает, надо через гугл искать.
     
  8. Blc_Dragon

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

    Баллы:
    76
    Имя в Minecraft:
    Blc_Dragon
    а нафига.

    e.getEnchantsToAdd() - это HasMap<Enchantment, Integer> - зачар\левел.
    Просто меняешь эту мапу на то что надо и никаких проблем
     
  9. Автор темы
    GreenBudgie

    GreenBudgie Ньюби Пользователь

    Баллы:
    1
    Так на обычные вещи чар кладется без проблем. С книгами - другое дело. Когда их чаришь, из одного айтемстака получается другой, а сама эта смена происходит уже после срабатывания эвента. Получается, что твой отредактированный предмет заменяется новым.
    Вопрос актуален. Попробовал добавить поток - но при его срабатывании предмет уже null. Прошу помочь с этим. Код ниже.
    Код:
    @EventHandler
        public void enchant(EnchantItemEvent e) {
            ItemStack item = e.getItem();
            Material m = item.getType();
            if(m == Material.CHAINMAIL_LEGGINGS || m == Material.DIAMOND_LEGGINGS || m == Material.GOLD_LEGGINGS
                    || m == Material.IRON_LEGGINGS || m == Material.LEATHER_LEGGINGS || m == Material.BOOK) {
                if(true) {
                    final int level = e.getExpLevelCost() > 20 ? (Math.random() > 0.5 ? 3 : 2)
                            : (Math.random() > 0.5 ? 2 : 1);
                    if(m != Material.BOOK) {
                        item.addEnchantment(EnchantmentManager.TEST_ENCH, level);
                    } else {
                        DoncPlugin.instance.getServer().getScheduler().scheduleSyncDelayedTask(DoncPlugin.instance,
                                new Runnable() {
                                    public void run() {
                                        try {
                                            DoncPlugin.log(item.getItemMeta().getDisplayName());
                                            EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemMeta();
                                            meta.addStoredEnchant(EnchantmentManager.TEST_ENCH, level, false);
                                            item.setItemMeta(meta);
                                        } catch(ClassCastException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }, 1L);
                    }
                    ItemMeta meta = item.getItemMeta();
                    List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<String>();
                    lore.add(ChatColor.GRAY + EnchantmentManager.TEST_ENCH.getName() + " "
                            + EnchantmentManager.getRomanNumber(level));
                    meta.setLore(lore);
                    item.setItemMeta(meta);
                }
            }
        }
    P.S. Есть еще одно решение - полная отмена события и выполнение всего процесса зачара самостоятельно. Но это потребует переписать всю систему чаров майна, а это как-то слишком.[DOUBLEPOST=1497633345,1497616918][/DOUBLEPOST]
    Это срочно, а решение я так и не нашел.
     
    Последнее редактирование: 16 июн 2017
  10. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    С книгой тебе нужно в результате получить книгу с зачарованием?
    Если да, то пробуй это.
    Код:
    List<Material> materials = Arrays.asList(new Material[]{
        Material.CHAINMAIL_LEGGINGS, Material.DIAMOND_LEGGINGS, Material.GOLD_LEGGINGS,
        Material.IRON_LEGGINGS, Material.LEATHER_LEGGINGS, Material.BOOK
    });
    
    @EventHandler
    public void enchant(EnchantItemEvent e) {
        ItemStack item = e.getItem();
        Material m = item.getType();
        if (!materials.contains(m)) {
            return;
        }
        int level = e.getExpLevelCost() > 20
                ? (Math.random() > 0.5 ? 3 : 2)
                : (Math.random() > 0.5 ? 2 : 1);
        if (m != Material.BOOK) {
            item.addEnchantment(EnchantmentManager.TEST_ENCH, level);
        } else {
            item.setType(Material.ENCHANTED_BOOK);
            EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemMeta();
            meta.addStoredEnchant(EnchantmentManager.TEST_ENCH, level, true);
            item.setItemMeta(meta);
        }
        ItemMeta meta = item.getItemMeta();
        List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
        lore.add(ChatColor.GRAY + EnchantmentManager.TEST_ENCH.getName() + " "
                + EnchantmentManager.getRomanNumber(level));
        meta.setLore(lore);
        item.setItemMeta(meta);
    }
     
    Последнее редактирование: 16 июн 2017
  11. TheZefirrkka

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

    Баллы:
    76
    Skype:
    RomaMamkinHasker1337
    Имя в Minecraft:
    TheZefirrkka
    1. int level = e.getExpLevelCost() > 20
    2. ? (Math.random() > 0.5 ? 3 : 2)
    3. : (Math.random() > 0.5 ? 2 : 1);
      Сложна. Но я понял
     
  12. Автор темы
    GreenBudgie

    GreenBudgie Ньюби Пользователь

    Баллы:
    1
    Также выглядел мой код до добавления в него потока - это не работает. Все из-за того что обычная книга заменяется на чареную уже ПОСЛЕ эвента, и все изменения в нем не учитываются.
    P.S.
    Экспрэшн в экспрешене, все норм
     
  13. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Зачарование книги возможно же только в наковальне, если я ничего не упускаю?
     
  14. TheZefirrkka

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

    Баллы:
    76
    Skype:
    RomaMamkinHasker1337
    Имя в Minecraft:
    TheZefirrkka
    Упускаешь
     
  15. Автор темы
    GreenBudgie

    GreenBudgie Ньюби Пользователь

    Баллы:
    1
    В чарку как бы давно уже можно книги совать.
    Ладно, здесь, кажется, ответа я не найду. Пойду на зарубежные форумы писать. Если решу проблему - напишу сюда, возможно кому-то пригодится.
    А так вопрос не закрыт. Если есть какие-то идеи - пишите.[DOUBLEPOST=1497653270,1497650984][/DOUBLEPOST]Короче, без всяких форумов допер как решить проблему. Все-таки помог delayedTask. Изначально я и думал так сделать, но почему-то не получалось. Теперь я допер и все ок, так что код ниже.
    Код:
        @EventHandler
        public void enchant(EnchantItemEvent e) {
            ItemStack item = e.getItem();
            Material m = item.getType();
            if(m == Material.CHAINMAIL_LEGGINGS || m == Material.DIAMOND_LEGGINGS || m == Material.GOLD_LEGGINGS
                    || m == Material.IRON_LEGGINGS || m == Material.LEATHER_LEGGINGS || m == Material.BOOK) {
                if(true) {
                    final int level = e.getExpLevelCost() > 20 ? (Math.random() > 0.5 ? 3 : 2)
                            : (Math.random() > 0.5 ? 2 : 1);
                    e.getEnchantsToAdd().put(EnchantmentManager.TEST_ENCH, level);
                    if(m == Material.BOOK) {
                        item.setType(Material.ENCHANTED_BOOK);
                        EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemMeta();
                        for(Enchantment ench : e.getEnchantsToAdd().keySet()) {
                            meta.addStoredEnchant(ench, e.getEnchantsToAdd().get(ench), false);
                        }
                        item.setItemMeta(meta);
                    }
                    ItemMeta meta = item.getItemMeta();
                    List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<String>();
                    lore.add(ChatColor.GRAY + EnchantmentManager.TEST_ENCH.getName() + " "
                            + EnchantmentManager.getRomanNumber(level));
                    meta.setLore(lore);
                    item.setItemMeta(meta);
                    if(m == Material.BOOK) {
                        DoncPlugin.instance.getServer().getScheduler().scheduleSyncDelayedTask(DoncPlugin.instance, new Runnable() {
                            final Player p = e.getEnchanter();
                            final ItemStack book = item;
                           
                            public void run() {
                                p.getOpenInventory().getTopInventory().setItem(0, book);
                            }
                        }, 1L);
                    }
                }
            }
        }
    Здесь я запускаю поток с задержкой в 1 тик, поэтому все происходит почти моментально.
     
  16. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Почитал nms. В итоге получилось это:
    Код:
    @EventHandler
    public void enchant(EnchantItemEvent e) {
        ItemStack item = e.getItem();
        Material m = item.getType();
        if (m != Material.BOOK) {
            return;
        }
    
        Inventory topInventory = e.getView().getTopInventory();
        new BukkitRunnable() {
            @Override
            public void run() {
                item.setType(Material.ENCHANTED_BOOK);
                EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemMeta();
                meta.addStoredEnchant(Enchantment.DIG_SPEED, 4, true);
                List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
                lore.add(ChatColor.GRAY + "Зачарено");
                meta.setLore(lore);
                item.setItemMeta(meta);
                topInventory.setItem(0, item);
            }
        }.runTask(this);
    }
    Итоговое значение:
    Код:
    List<Material> materials = Arrays.asList(new Material[]{
        Material.CHAINMAIL_LEGGINGS, Material.DIAMOND_LEGGINGS, Material.GOLD_LEGGINGS,
        Material.IRON_LEGGINGS, Material.LEATHER_LEGGINGS, Material.BOOK
    });
    
    @EventHandler
    public void enchant(EnchantItemEvent e) {
        ItemStack item = e.getItem();
        Material m = item.getType();
        if (!materials.contains(m)) {
            return;
        }
        int level = e.getExpLevelCost() > 20
                ? (Math.random() > 0.5 ? 3 : 2)
                : (Math.random() > 0.5 ? 2 : 1);
        if (m != Material.BOOK) {
            item.addEnchantment(EnchantmentManager.TEST_ENCH, level);
        } else {
            Inventory topInventory = e.getView().getTopInventory();
            new BukkitRunnable() {
                @Override
                public void run() {
                    DoncPlugin.log(item.getItemMeta().getDisplayName());
                    EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemMeta();
                    meta.addStoredEnchant(EnchantmentManager.TEST_ENCH, level, false);
                    item.setItemMeta(meta);
                    topInventory.setItem(0, item);
                }
            }.runTask(DoncPlugin.instance);
        }
        ItemMeta meta = item.getItemMeta();
        List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
        lore.add(ChatColor.GRAY + EnchantmentManager.TEST_ENCH.getName() + " "
                + EnchantmentManager.getRomanNumber(level));
        meta.setLore(lore);
        item.setItemMeta(meta);
    }
     
  17. TheZefirrkka

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

    Баллы:
    76
    Skype:
    RomaMamkinHasker1337
    Имя в Minecraft:
    TheZefirrkka
    Зачем так по научному называть обычный if?(Да, это обычный if, просто пишется по другому, но я опережу "знатоков" и дополню, что это называется ещё и тернарный оператор)
     
    Последнее редактирование: 17 июн 2017
  18. Автор темы
    GreenBudgie

    GreenBudgie Ньюби Пользователь

    Баллы:
    1
    Так это не обычный if, а именно expression) Выражениями записывать компактнее, хоть и не всегда удобнее. В данном случае моя переменная финальная, и никаких if после нее быть не должно. Вот и юзаю выражения)
     
  19. TheZefirrkka

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

    Баллы:
    76
    Skype:
    RomaMamkinHasker1337
    Имя в Minecraft:
    TheZefirrkka
    Заного прочитай моё сообщение, я тебя на минуту опередил.[DOUBLEPOST=1497657030,1497656929][/DOUBLEPOST]Кстати, в русском языке "if" это "ША"[DOUBLEPOST=1497657122][/DOUBLEPOST]
    А теперь докажи, что это не обычный if...По факту просто сокращение.
     
  20. Автор темы
    GreenBudgie

    GreenBudgie Ньюби Пользователь

    Баллы:
    1
    Кстати не знал, спасибо)
    Тебе лучше знать, я и не настаивал)
     
  21. TheZefirrkka

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

    Баллы:
    76
    Skype:
    RomaMamkinHasker1337
    Имя в Minecraft:
    TheZefirrkka
    А я их редко использую... Да и часто забываю, что они вообще существуют))
     

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