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

Помогите Крафт из кастомных предметов и их переплавка

Тема в разделе "Разработка плагинов для новичков", создана пользователем fx8320e, 2 апр 2021.

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

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

    Баллы:
    66
    Приветствую! Столкнулся с такой проблемой: у меня есть некоторый ресурс (Мифриловая руда), и мне нужно переплавить ее в слитки.
    PHP:
        @EventHandler
        
    public void onBlockBreak1(BlockBreakEvent e) {
            
    Block block e.getBlock();
            
    Player p e.getPlayer();
           
           

            if (
    block.getType() == Material.GOLD_ORE && p.getInventory().getItemInMainHand().getType() == Material.NETHERITE_PICKAXE) {
                
    Location location block.getLocation();
                
    ItemStack mo = new ItemStack(Material.GOLD_ORE);
                  
    ItemMeta meta mo.getItemMeta();
                  
    meta.setDisplayName(ChatColor.AQUA "Мифриловая руда");
                  
    mo.setItemMeta(meta);


                
    e.setDropItems(false);
                
    location.getWorld().dropItemNaturally(locationmo);
            } 
    Собственно, необходимо, чтобы только железная руда с meta.setDisplayName(ChatColor.AQUA + "Мифриловая руда"); после обработки превращалась в мифриловые слитки, а не вся. И, самое главное, требуется задействовать эти новые слитки в крафтах. Поискал в интернете, некоторые говорят, что нужно использовать PrepareItemCraftEvent (Голову всю сломал, но так и не понял, как это работает), некоторые, что можно через ItemStack. Однако, четкого ответа не нашел. Знающие люди, пожалуйста, помогите. Предупрежу сразу, плагины начал писать совсем недавно, потому могут быть глупые вопросы. Заранее благодарю!
     
  2. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    Слушай FurnaceSmeltEvent - проверь тип и наличие названия у event.getSource(), и если всё правильно, то event.setResult(твой мифриловый слиток).
    Если нужное просто решение, без нервотрепки, то как-то так:
    С PrepareItemCraftEvent достаешь инвентарь верстака - CraftingInventory craft = event.getInventory()
    Проверь craft.getType() == InventoryType.WORKBENCH
    Далее получаешь матрицу верстака (окно 3x3) - ItemStack[] matrix = craft.getMatrix()
    Матрица выглядит так
    Код:
    0 1 2
    3 4 5
    6 7 8
    Наконец, тебе нужно просто сравнить свой рецепт с этой матрицей, проверяя каждый предмет из массива, и если совпадает, craft.setResult(твой новый предмет)

    Для более "мудрого" решения возможно захочешь взглянуть в эту тему - пускай там речь про 4х4, но способ, в целом, сработает и для иных масштабов.
     
  3. Автор темы
    fx8320e

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

    Баллы:
    66
    Спасибо! Сделал, все работает.
     
  4. Автор темы
    fx8320e

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

    Баллы:
    66
    Хотя, к сожалению, не совсем. Возник странный баг, при крафте количество предметов изменяется с n на (n-1)*2. Скриншот и код прилагаю.
    PHP:
     [ATTACH]59120[/ATTACH]
    @
    EventHandler
        
    public void PallDr(PrepareItemCraftEvent  event) {
       
            
    ItemStack woodendagger = new ItemStack(Material.NAUTILUS_SHELL);
            
    ItemMeta meta woodendagger.getItemMeta();
                
    meta.setDisplayName(ChatColor.DARK_BLUE "Палладиевый слиток");
                
    woodendagger.setItemMeta(meta);   
               
                
    ItemStack woodendagge = new ItemStack(Material.NETHERITE_SWORD1);
                
    ItemMeta me woodendagge.getItemMeta();
                
    AttributeModifier modifier = new AttributeModifier(UUID.randomUUID(), "generic.attackDamage"7AttributeModifier.Operation.ADD_NUMBEREquipmentSlot.HAND);
                
    me.addAttributeModifier(Attribute.GENERIC_ATTACK_DAMAGEmodifier);
                
    AttributeModifier modifier2 = new AttributeModifier(UUID.randomUUID(), "generic.attackSpeed"2AttributeModifier.Operation.ADD_NUMBEREquipmentSlot.HAND);
                
    me.addAttributeModifier(Attribute.GENERIC_ATTACK_SPEEDmodifier2);
                
    me.setDisplayName(ChatColor.DARK_BLUE "Палладиевый кинжал");
                
    woodendagge.setItemMeta(me);
                 
            
    CraftingInventory craft event.getInventory();
            
    ItemStack[] matrix craft.getMatrix();
            if(
    craft.getType() == InventoryType.WORKBENCH
                    
    && matrix[0] == null
                    
    && matrix[1] == null 
                    
    && matrix[2] == null 
                    
    && matrix[3] == null 
                    
    && matrix[4] != null && matrix[4].getType() == Material.NAUTILUS_SHELL && matrix[4].hasItemMeta() && matrix[4].getItemMeta().equals(meta)
                    && 
    matrix[5] == null 
                    
    && matrix[6] == null
                    
    && matrix[7] != null && matrix[7].getType() == Material.STICK
                    
    && matrix[8] == null) {
               

                        
    event.getInventory().setResult(woodendagge);
            }   
        }
     
  5. Автор темы
    fx8320e

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

    Баллы:
    66
    Почему-то не прикрепился...
     

    Вложения:

  6. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    Довольно странно. Впрочем, есть иной, более практичный способ - через непосредственно рецепты. Раньше они не поддерживали названия и прочее, но теперь, похоже, работают с ними.

    Во-первых, нэймспейс ключ - он тебе пригодится для регистрации рецепта. Для каждого рецепта, соответственно, свой ключ. Например new NamespacedKey(plugin, "mythril_sword") - ключ обязательно должен быть маленькими английскими буквами и _ в качестве пробела.
    Создаешь рецепт ShapedRecipe recipe = new ShapedRecipe(new NamespacedKey(plugin, "mythril_sword"), mythrilSword), где mythrilSword - твой предмет.
    Далее делаешь для него матрицу
    PHP:
    recipe.shape(
        
    " i ",
        
    " i ",
        
    " s ",
    );
    Каждый символ - какой-то ингредиент, и для их указания нужно воспользоваться recipe.setIngredient(). Чтобы указать там предмет с данными, нужно воспользоваться RecipeChoice.ExactChoice - сохрани свой слиток в виде этого класса где-нибудь, чтоб использовать повторно - RecipeChoice mythrilChoice = new RecipeChoice.ExactChoice(mythrilIngot), где mythrilIngot твой слиток.
    Далее, просто укажи сами ингредиенты
    PHP:
    recipe.setIngredient('i'mythrilChoice);
    recipe.setIngredient('s'Material.STICK)
    Наконец, его нужно зарегистрировать на сервере
    PHP:
    Bukkit.addRecipe(recipe)
     
  7. Автор темы
    fx8320e

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

    Баллы:
    66
    Спасибо. Как составлять обычные рецепты я знаю, но кастомный работать не хочет. Вот код, похоже на правду?
    PHP:
        private void pallsth() {
          
            
    ItemStack woodendagger = new ItemStack(Material.NETHERITE_SWORD);
            
    ItemMeta meta woodendagger.getItemMeta();
                
    meta.setDisplayName(ChatColor.WHITE "Палладиевая коса");
                
    AttributeModifier modifier = new AttributeModifier(UUID.randomUUID(), "generic.attackDamage"11AttributeModifier.Operation.ADD_NUMBEREquipmentSlot.HAND);
                
    meta.addAttributeModifier(Attribute.GENERIC_ATTACK_DAMAGEmodifier);
                
    AttributeModifier modifier2 = new AttributeModifier(UUID.randomUUID(), "generic.attackSpeed"3AttributeModifier.Operation.ADD_NUMBEREquipmentSlot.HAND);
                
    meta.addAttributeModifier(Attribute.GENERIC_ATTACK_SPEEDmodifier2);
                
    woodendagger.setItemMeta(meta);
                
    ItemStack mythrilIngot = new ItemStack(Material.NAUTILUS_SHELL);
                
    RecipeChoice mythrilChoice = new RecipeChoice.ExactChoice(mythrilIngot);
            
    NamespacedKey dsKey = new NamespacedKey(this"diamondscythe");

                
    ShapedRecipe diamonddaggerR = new ShapedRecipe(dsKeywoodendagger);

                
    diamonddaggerR.shape("ooo""ggu""gug");
                
    diamonddaggerR.setIngredient('o'mythrilChoice);
                
    diamonddaggerR.setIngredient('u'Material.STICK);
                
    diamonddaggerR.setIngredient('g'Material.AIR);
                
    getServer().addRecipe(diamonddaggerR);

        }
    Строка RecipeChoice mythrilChoice = new RecipeChoice.ExactChoice(mythrilIngot); значится ошибочной.
     
  8. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    А какая именно ошибка?
     
  9. Автор темы
    fx8320e

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

    Баллы:
    66
    @SuppressWarnings("deprecation") ExactChoice зачеркнуто.
     
  10. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    Это нормально. Если глянешь javadoc этого класса, увидишь, что у него написано "draft API" - значит это черновой вариант апи. Он может быть изменен позже, поэтому висит предупреждение.
     
  11. Автор темы
    fx8320e

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

    Баллы:
    66
    При этом оно не работает.
     
  12. imDaniX

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

    Баллы:
    96
    Имя в Minecraft:
    imDaniX
    Попробуй не указывать воздух в рецепте.
     
  13. Автор темы
    fx8320e

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

    Баллы:
    66
    Все еще не работает.
     
  14. alexandrage

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

    Баллы:
    173
    Поменяй на new RecipeChoice.MaterialChoice(mythrilIngot.getType())
     
  15. Автор темы
    fx8320e

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

    Баллы:
    66
    Все равно не работает. Среда разработки предлагает заменить ItemStack на Material в этой строчке ItemStack mythrilIngot = new ItemStack(Material.NAUTILUS_SHELL); и наоборот.
     
  16. Автор темы
    fx8320e

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

    Баллы:
    66
    А. Все, с .getType() работает. Спасибо!
     
  17. Автор темы
    fx8320e

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

    Баллы:
    66
    Но получается, что оно работает со всеми предметами этого типа. И мета никак на крафт не влияет.
     
  18. alexandrage

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

    Баллы:
    173
    Так это механика крафтов, там только материал проверяется.
     
  19. alexandrage

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

    Баллы:
    173
  20. Автор темы
    fx8320e

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

    Баллы:
    66
    Мне нужно, чтобы крафт работал именно из кастомных штук с определенной метой. Оно работает через PrepareCraftEvent, но с багом: http://rubukkit.org/threads/strannyj-bag-v-prepareitemcraftevent.175951/
     

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