Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

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

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(location, mo);
        }
Собственно, необходимо, чтобы только железная руда с meta.setDisplayName(ChatColor.AQUA + "Мифриловая руда"); после обработки превращалась в мифриловые слитки, а не вся. И, самое главное, требуется задействовать эти новые слитки в крафтах. Поискал в интернете, некоторые говорят, что нужно использовать PrepareItemCraftEvent (Голову всю сломал, но так и не понял, как это работает), некоторые, что можно через ItemStack. Однако, четкого ответа не нашел. Знающие люди, пожалуйста, помогите. Предупрежу сразу, плагины начал писать совсем недавно, потому могут быть глупые вопросы. Заранее благодарю!
 
Собственно, необходимо, чтобы только железная руда с meta.setDisplayName(ChatColor.AQUA + "Мифриловая руда"); после обработки превращалась в мифриловые слитки.
Слушай FurnaceSmeltEvent - проверь тип и наличие названия у event.getSource(), и если всё правильно, то event.setResult(твой мифриловый слиток).
Поискал в интернете, некоторые говорят, что нужно использовать PrepareItemCraftEvent
Если нужное просто решение, без нервотрепки, то как-то так:
С 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, но способ, в целом, сработает и для иных масштабов.
 
Слушай 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, но способ, в целом, сработает и для иных масштабов.
Хотя, к сожалению, не совсем. Возник странный баг, при крафте количество предметов изменяется с 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_SWORD, 1);
            ItemMeta me = woodendagge.getItemMeta();
            AttributeModifier modifier = new AttributeModifier(UUID.randomUUID(), "generic.attackDamage", 7, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.HAND);
            me.addAttributeModifier(Attribute.GENERIC_ATTACK_DAMAGE, modifier);
            AttributeModifier modifier2 = new AttributeModifier(UUID.randomUUID(), "generic.attackSpeed", 2, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.HAND);
            me.addAttributeModifier(Attribute.GENERIC_ATTACK_SPEED, modifier2);
            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);
        }   
    }
 

Вложения:

  • 2021-04-04_00.11.37.png
    2021-04-04_00.11.37.png
    Размер файла
    289,5 КБ
    Просмотров
    0
Почему-то не прикрепился...
 

Вложения:

  • 2021-04-04_00.11.37.png
    2021-04-04_00.11.37.png
    Размер файла
    289,5 КБ
    Просмотров
    14
Довольно странно. Впрочем, есть иной, более практичный способ - через непосредственно рецепты. Раньше они не поддерживали названия и прочее, но теперь, похоже, работают с ними.

Во-первых, нэймспейс ключ - он тебе пригодится для регистрации рецепта. Для каждого рецепта, соответственно, свой ключ. Например 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)
 
Довольно странно. Впрочем, есть иной, более практичный способ - через непосредственно рецепты. Раньше они не поддерживали названия и прочее, но теперь, похоже, работают с ними.

Во-первых, нэймспейс ключ - он тебе пригодится для регистрации рецепта. Для каждого рецепта, соответственно, свой ключ. Например 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)
Спасибо. Как составлять обычные рецепты я знаю, но кастомный работать не хочет. Вот код, похоже на правду?
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", 11, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.HAND);
            meta.addAttributeModifier(Attribute.GENERIC_ATTACK_DAMAGE, modifier);
            AttributeModifier modifier2 = new AttributeModifier(UUID.randomUUID(), "generic.attackSpeed", 3, AttributeModifier.Operation.ADD_NUMBER, EquipmentSlot.HAND);
            meta.addAttributeModifier(Attribute.GENERIC_ATTACK_SPEED, modifier2);
            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(dsKey, woodendagger);

            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); значится ошибочной.
 
@SuppressWarnings("deprecation") ExactChoice зачеркнуто.
Это нормально. Если глянешь javadoc этого класса, увидишь, что у него написано "draft API" - значит это черновой вариант апи. Он может быть изменен позже, поэтому висит предупреждение.
 
Это нормально. Если глянешь javadoc этого класса, увидишь, что у него написано "draft API" - значит это черновой вариант апи. Он может быть изменен позже, поэтому висит предупреждение.
При этом оно не работает.
 
Поменяй на new RecipeChoice.MaterialChoice(mythrilIngot.getType())
Все равно не работает. Среда разработки предлагает заменить ItemStack на Material в этой строчке ItemStack mythrilIngot = new ItemStack(Material.NAUTILUS_SHELL); и наоборот.
 

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

Назад
Верх