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

Помогите Некорректная работа PrepareCraftItemEvent [Решено]

Тема в разделе "Разработка плагинов для новичков", создана пользователем _TheZit445_, 13 фев 2019.

Статус темы:
Закрыта.
  1. Автор темы
    _TheZit445_

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

    Баллы:
    76
    Skype:
    kirik2425
    Имя в Minecraft:
    _TheZit445_
    Приветствую. Маленькая предыстория. Хочу реализовать кастомный крафт. Использую данный ивент. Сами крафты работают исправно, то что надо крафтится, но предметы в слотах верстака ведут себя некорректно. Допустим такой крафт: из одного алмаза получаем изумруд. Так вот если положить один алмаз, то все нормально, алмаз исчезнет, а мы получим изумруд, ео если два, то мы получим изумруд, но в слоте как было два алмаза, так и останется два алмаза. Дальше вообще абсурд. Если было 3 алмаза, станет 4, если 4, будет 6, если 5, то станет 8, если 6, то будет 10 и так далее, закономерность думаю ясна. Реализовано так - я грубо говоря проверяю слот верстака с необходимым предметом. Если всё успешно, то выводим результат. И вообще, кастомные рецепты так реализуются или как-то иначе. Я стараюсь сделать с поддержкой NBT, ибо иначе зачем вообще морочится. Если нужен будет код, кину.

    upload_2019-2-13_19-36-55.png
     
  2. Ission

    Ission Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    lokivava
    Ну код безусловно нужен. Тут же ясно, что у вас что-то не так с кодом. Каждый алгоритм реализовать можно бесчисленным количеством способов. Я, например, для кастомных крафтов с NBT использовал добавление рецепта в список стандартных, после чего его отслеживал и заменял результат на нужный элемент в том же событии.
     
  3. Автор темы
    _TheZit445_

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

    Баллы:
    76
    Skype:
    kirik2425
    Имя в Minecraft:
    _TheZit445_
    Код чуть позже. Если бы мне нужно было заменить именно результат, я бы поступил так же наверное, но я ещё проверяю сами ингредиенты, на наличие nbt.
     
  4. Автор темы
    _TheZit445_

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

    Баллы:
    76
    Skype:
    kirik2425
    Имя в Minecraft:
    _TheZit445_
    Класс с конструктором рецепта
    Код:
    package ru.thezit445.CraftingAPI.recipes;
    
    import java.util.HashMap;
    
    import org.bukkit.Material;
    import org.bukkit.craftbukkit.v1_13_R2.inventory.CraftItemStack;
    import org.*********ventory.ItemStack;
    
    import com.google.gson.Gson;
    
    import net.minecraft.server.v1_13_R2.NBTTagCompound;
    import ru.thezit445.CraftingAPI.crafting.DummyItem;
    
    public class ShapedNBT_Recipe extends NBT_Recipe{
       
        private String[] PATTERN = new String[3];
        private HashMap<String, DummyItem> ITEMS = new HashMap<String, DummyItem>();
        private DummyItem RESULT;
       
        public ShapedNBT_Recipe(RecipeType type) {
            super(type);
            ITEMS.put(" ", new DummyItem(Material.AIR, null));
        }
       
        public int getHorizontalPatternSize() {
            int size = 0;
            for (String layer : PATTERN) {
                if (layer == null) continue;
                if (size < layer.length()) {
                    size = layer.length();
                }
            }
            return size;
        }
       
        public int getVerticalPatternSize() {
            int size = 0;
            for (int i = 0; i<3; i++) {
                if (PATTERN[i]!=null && !PATTERN[i].isEmpty()) size++;
            }
            return size;
        }
       
        public void setResult(ItemStack item) {
           
            CraftItemStack craftItem = CraftItemStack.asCraftCopy(item);
            NBTTagCompound NBT = new NBTTagCompound();
            CraftItemStack.asNMSCopy(craftItem).save(NBT);
            RESULT = new DummyItem(item.getType(), NBT);
           
        }
       
        public ItemStack getResult() {
           
            NBTTagCompound NBT = RESULT.getNBT();
            net.minecraft.server.v1_13_R2.ItemStack nmsItem = net.minecraft.server.v1_13_R2.ItemStack.a(NBT);
            ItemStack item = CraftItemStack.asBukkitCopy(nmsItem);
           
            return item;
           
        }
       
        public void setItemKey(String key, ItemStack item) {
           
            CraftItemStack craftItem = CraftItemStack.asCraftCopy(item);
            NBTTagCompound NBT = new NBTTagCompound();
            CraftItemStack.asNMSCopy(craftItem).save(NBT);
            ITEMS.put(key, new DummyItem(item.getType(), NBT));
           
        }
       
        public DummyItem getDummyItemKey(String key) {
            return ITEMS.get(key);
        }
       
        public void setItems(HashMap<String, DummyItem> items) {
            ITEMS = items;
        }
       
        public ItemStack getItem(String key) {
           
            NBTTagCompound NBT = ITEMS.get(key).getNBT();
            net.minecraft.server.v1_13_R2.ItemStack nmsItem = net.minecraft.server.v1_13_R2.ItemStack.a(NBT);
            ItemStack item = CraftItemStack.asBukkitCopy(nmsItem);
            return item;
           
        }
       
        public void setFirstLayerForPattern(String layer) {
            PATTERN[0] = layer;
        }
    
        public void setSecondLayerForPattern(String layer) {
            PATTERN[1] = layer;
        }
       
        public void setThriedLayerForPattern(String layer) {
            PATTERN[2] = layer;
        }
       
        public void setPattern(String[] pattern) {
            PATTERN = pattern;
        }
       
        public String[] getPattern() {
            return PATTERN;
        }
       
        public String getLayer(int layerNumber) {
            return PATTERN[layerNumber];
        }
       
        @Override
        public String toJsonString() {
            Gson gson = new Gson();
            return gson.toJson(this, ShapedNBT_Recipe.class);
        }
    
        public static NBT_Recipe getCraft(String json) {
            Gson gson = new Gson();
            return gson.fromJson(json, ShapedNBT_Recipe.class);
        }
    
    }

    Класс с обработчиком события крафта
    Код:
    package ru.thezit445.CraftingAPI.crafting_handlers;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.List;
    
    import org.bukkit.Material;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.inventory.PrepareItemCraftEvent;
    import org.*********ventory.ItemStack;
    
    import ru.thezit445.CraftingAPI.crafting.DummyItem;
    import ru.thezit445.CraftingAPI.main.CraftingAPI;
    import ru.thezit445.CraftingAPI.recipes.ShapedNBT_Recipe;
    import ru.thezit445.CraftingAPI.util.NBT_Manager;
    
    public class ShapedHandler implements Listener{
    
        @EventHandler
        public void handler(PrepareItemCraftEvent event) {
            Iterator<ShapedNBT_Recipe> iterator = CraftingAPI.SHAPED_RECIPES.iterator();
            ItemStack[] matrix = event.getInventory().getMatrix();
            while (iterator.hasNext()) {
                ShapedNBT_Recipe recipe = iterator.next();
                boolean[] confirmItems = new boolean[recipe.getHorizontalPatternSize()*recipe.getVerticalPatternSize()];
                Arrays.fill(confirmItems, false);
                int hx = 3-recipe.getHorizontalPatternSize();
                int hy = 3-recipe.getVerticalPatternSize();
                List<Integer> activeItems = new ArrayList<Integer>();
                for (int i = 0; i<=hy; i++) {
                    for (int j = 0; j<=hx; j++) {
                        activeItems.clear();
                        for (int y = (0+i); y<(recipe.getVerticalPatternSize()+i); y++) {
                            for (int x = (0+j); x<(recipe.getHorizontalPatternSize()+j); x++) {
                               
                                activeItems.add(x+y*3);
                               
                               
                                ItemStack item = matrix[x+y*3];
                                ItemStack sample = recipe.getItem(""+recipe.getPattern()[y-i].charAt(x-j));
                                DummyItem dummy = recipe.getDummyItemKey(""+recipe.getPattern()[y-i].charAt(x-j));
                               
                                if (item==null && dummy.getMaterial()==Material.AIR) {
                                    confirmItems[(x-j)+((y-i)*3)] = true;
                                } else 
                                    if (item!=null && item.getType()==dummy.getMaterial()) {
                                        if (dummy.hasCustomNBT()) {
                                            if (dummy.getNBT().get("tag").equals(NBT_Manager.getNBT(item))) {
                                                confirmItems[(x-j)+((y-i)*3)] = true;
                                            } else {
                                                confirmItems[(x-j)+((y-i)*3)] = false;
                                            }
                                        } else {
                                            confirmItems[(x-j)+((y-i)*3)] = true;
                                        }
                                    } else { 
                                        confirmItems[(x-j)+((y-i)*3)] = false;
                                    }
                               
                            }
                        }
                       
                        boolean complete = true;
                        for (int g = 0; g<confirmItems.length; g++) {
                            complete = (complete && confirmItems[g]);
                        }
                       
                        for (int s = 0; s<9; s++) {
                            if (activeItems.contains(s)) continue;
                            if (matrix[s]!=null) complete = false;
                        }
                       
                        if (complete) {
                            event.getInventory().setResult(recipe.getResult());
                            return;
                        } else {
                            if (event.getInventory().getRecipe() != null) {
                                event.getInventory().setResult(event.getInventory().getRecipe().getResult());
                            } else {
                                event.getInventory().setResult(new ItemStack(Material.AIR));
                            }
                        }
                       
                        Arrays.fill(confirmItems, false);
                    }
                }
            }
        }
       
    }
     
  5. Ission

    Ission Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    lokivava
    Ну так я и проверяю наличие nbt у ингредиентов, потому что мне нужно, чтобы из предметов с разными названиями крафтились разные результаты.
     
  6. Автор темы
    _TheZit445_

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

    Баллы:
    76
    Skype:
    kirik2425
    Имя в Minecraft:
    _TheZit445_
    Есть какой-нибудь клочок кода, я бы глянул. И я еще кое-что нашёл, но пока не разбирался, но там это реализовано. Если можешь, поделись пожалуйста.
     
  7. Ission

    Ission Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    lokivava
    У меня это так делается:
    Код:
    @EventHandler
        public void onCraft(org.bukkit.event.inventory.PrepareItemCraftEvent e)
        {
            if(e.getRecipe()==null || e.getRecipe().getResult()==null)
                return;
            for(EternalRecipe er: recipes.get(e.getRecipe().getResult().getType()))
                if(er.isIt(e.getInventory()))
                {
                    e.getInventory().setResult(er.getResult());
                    return;
                }
            e.getInventory().setResult(null);
        }
    
     
  8. alexandrage

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

    Баллы:
    173
    Вот удобная либа на кастом крафт https://github.com/alexandrage/Craft
    Работает через конфиг. Ловит шапедрецепт и чекает мету предметов в сетке крафта.
     
  9. Автор темы
    _TheZit445_

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

    Баллы:
    76
    Skype:
    kirik2425
    Имя в Minecraft:
    _TheZit445_
    @alexandrage , @Ission , спасибо за помощь. Добил свою реализацию, полностью ее переписал, оставив идею. Перенял некоторые вещи у вас. В общем то сатанинское кол-во, которое получалось в сетке крафта, не мой грех (ну или немножко мой). После того как переписал с нуля, количество предметов в сетке просчитывается правильно, но с визуальным багом. Было нечто похожее на то, что описано в проблеме, но через долю секунды количество устанавливалось правильным. Я так понял, что это связанно с новой реализацией крафтов на 1.13, ибо я использовал ShapedRecipe(ItemStack result), который уже считается устаревшим, возможно он даёт осложнение, ведь даже когда я не использую обработку ивента, визуальный баг есть.
     
Статус темы:
Закрыта.

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