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

GreenBudgie

Участник
Пользователь
Баллы
31
Мне нужно добавить собственный энчант в книгу при ее зачаровании. Пытаюсь сделать через EnchantItemEvent, но есть проблема. Майн меняет обычную книгу на зачарованную уже после срабатывания эвента, а поэтому не получается изменить EnchantmentStorageMeta. Был вариант создать поток и через несколько миллисекунд поменять EnchantmentStorageMeta у книги, но этот способ мне кажется не очень стабильным.
 
Было бы странно, если бы я не сунулся сразу в гугл. Нет, ни на русскоязычных форумах, ни на иностранных прямого ответа я не нашел. Искал по сурсам разных плагинов на гитхабе, связанных с зачарами - но и там ничего не нашел (в этих плагинах все происходит через команды, а не через чарку).
 
Было бы странно, если бы я не сунулся сразу в гугл. Нет, ни на русскоязычных форумах, ни на иностранных прямого ответа я не нашел. Искал по сурсам разных плагинов на гитхабе, связанных с зачарами - но и там ничего не нашел (в этих плагинах все происходит через команды, а не через чарку).
Месяц-два назад в этом разделе была про это тема... Плохо искал
но этот способ мне кажется не очень стабильным.
Почему?
 
Месяц-два назад в этом разделе была про это тема... Плохо искал
Поиск не дает результатов. Можно ссылку?
Если что-то будет происходить не моментально, то есть небольшой шанс того, что игрок уже закроет инвентарь по Esc и доп. зачар просто не успеет наложиться. Хотя потоки для меня еще не совсем понятны, но все же задержки - это нехорошо. Однако, если других вариантов не будет, то сделаю так.
 
Поиск не дает результатов. Можно ссылку?

Если что-то будет происходить не моментально, то есть небольшой шанс того, что игрок уже закроет инвентарь по Esc и доп. зачар просто не успеет наложиться. Хотя потоки для меня еще не совсем понятны, но все же задержки - это нехорошо. Однако, если других вариантов не будет, то сделаю так.
Так просто следай минимальную задержку, 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. Есть еще одно решение - полная отмена события и выполнение всего процесса зачара самостоятельно. Но это потребует переписать всю систему чаров майна, а это как-то слишком.
Вопрос актуален.
Это срочно, а решение я так и не нашел.
 
Последнее редактирование:
С книгой тебе нужно в результате получить книгу с зачарованием?
Если да, то пробуй это.
Java:
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);
}
 
Последнее редактирование:
  1. int level = e.getExpLevelCost() > 20
  2. ? (Math.random() > 0.5 ? 3 : 2)
  3. : (Math.random() > 0.5 ? 2 : 1);
    Сложна. Но я понял
 
Если да, то пробуй это.
Также выглядел мой код до добавления в него потока - это не работает. Все из-за того что обычная книга заменяется на чареную уже ПОСЛЕ эвента, и все изменения в нем не учитываются.
P.S.
Сложна. Но я понял
Экспрэшн в экспрешене, все норм
 
Также выглядел мой код до добавления в него потока - это не работает. Все из-за того что обычная книга заменяется на чареную уже ПОСЛЕ эвента, и все изменения в нем не учитываются.
Зачарование книги возможно же только в наковальне, если я ничего не упускаю?
 
В чарку как бы давно уже можно книги совать.
Ладно, здесь, кажется, ответа я не найду. Пойду на зарубежные форумы писать. Если решу проблему - напишу сюда, возможно кому-то пригодится.
А так вопрос не закрыт. Если есть какие-то идеи - пишите.
Короче, без всяких форумов допер как решить проблему. Все-таки помог 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 тик, поэтому все происходит почти моментально.
 
Почитал nms. В итоге получилось это:
Java:
@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);
}
Итоговое значение:
Java:
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);
}
 
Экспрэшн в экспрешене
Зачем так по научному называть обычный if?(Да, это обычный if, просто пишется по другому, но я опережу "знатоков" и дополню, что это называется ещё и тернарный оператор)
 
Последнее редактирование:
Зачем так по научному называть обычный if?
Так это не обычный if, а именно expression) Выражениями записывать компактнее, хоть и не всегда удобнее. В данном случае моя переменная финальная, и никаких if после нее быть не должно. Вот и юзаю выражения)
 
Так это не обычный if, а именно expression) Выражениями записывать компактнее, хоть и не всегда удобнее. В данном случае моя переменная финальная, и никаких if после нее быть не должно. Вот и юзаю выражения)
Заного прочитай моё сообщение, я тебя на минуту опередил.
Кстати, в русском языке "if" это "ША"
Так это не обычный if
А теперь докажи, что это не обычный if...По факту просто сокращение.
 
Так это не обычный if, а именно expression) Выражениями записывать компактнее, хоть и не всегда удобнее. В данном случае моя переменная финальная, и никаких if после нее быть не должно. Вот и юзаю выражения)
А я их редко использую... Да и часто забываю, что они вообще существуют))
 
Назад
Верх