Помогите Самописные зачарования

TwentiethAutumn

Новичок
Баллы
6
В процессе создания самописных зачарований столкнулся с небольшой проблемой. В основной программе происходит регистрация зачарования, но командой /enchant зачаровать не удается(пишет, что зачарование с таким ID отсутствует). При /reload'е же пишет, что зачарование с таким ID уже зарегистрировано. Обьясните, пожалуйста
Upd1. Ошибок в консоли нет, Listener зачарования работает без ошибок. Так же можно выдать предмет с зачарованием.
Upd2. Команда "/give 2dolboeba minecraft:diamond_sword 1 0 {ench:[{id:70,lvl:2}]}" тоже работает исправно (70 - id моего зачарования)
Upd3. Если выдавать книгу, хранящую в себе зачарование, то стандартные зачарования работают корректно, а моим ничего нельзя зачаровать
Upd4. Версия spigot'a - spigot-1.8.8-R0.1-SNAPSHOT-latest
Код:
package ru.Trash.main;

import java.util.ArrayList;
import java.util.logging.Logger;

import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;

import ru.Trash.enchantments.BackstabEnchantment;
import ru.Trash.enchantments.EnchantmentTemplate;

public class Main extends JavaPlugin{
    
    public static PluginManager pluginManager;
    public static Logger logger;
    public static Plugin plugin;
    
    public static BackstabEnchantment BACKSTAB;
    
    public static ArrayList<EnchantmentTemplate> enchantmentList;
    
    @Override
    public void onEnable()
    {
        logger = this.getLogger();
        pluginManager = this.getServer().getPluginManager();
        enchantmentList = new ArrayList<EnchantmentTemplate>();
        plugin = Main.getPlugin(Main.class);
        
        BACKSTAB = new BackstabEnchantment(70);
        //type enchantment init here
    }
}
Код:
package ru.Trash.enchantments;

import java.lang.reflect.Field;
import java.util.Arrays;

import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.event.Listener;
import org.*********ventory.ItemStack;

import ru.Trash.main.Main;

public class EnchantmentTemplate extends Enchantment {

    public EnchantmentTemplate(int id) {
        super(id);
        fix(this);
        // TODO Auto-generated constructor stub
    }

    @Override
    public boolean canEnchantItem(ItemStack arg0) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean conflictsWith(Enchantment arg0) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public EnchantmentTarget getItemTarget() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getMaxLevel() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public String getName() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getStartLevel() {
        // TODO Auto-generated method stub
        return 0;
    }
    
    public void setListener(Listener listener) {
        Main.pluginManager.registerEvents(listener, Main.plugin);
    }
    
    private void fix(EnchantmentTemplate ench) {
        try {
            Field f = Enchantment.class.getDeclaredField("acceptingNew");
            f.setAccessible(true);
            f.set(null, true);
            if(Arrays.asList(Enchantment.values()).contains(ench) == false){
                Enchantment.registerEnchantment(ench);
                 Main.enchantmentList.add(this);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
Код:
package ru.Trash.enchantments;

import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.*********ventory.ItemStack;

import ru.Trash.listeners.BackstabListener;

public class BackstabEnchantment extends EnchantmentTemplate {

    public BackstabEnchantment(int id) {
        super(id);
        setListener(new BackstabListener());
        // TODO Auto-generated constructor stub
    }
    
    @Override
    public boolean canEnchantItem(ItemStack arg0) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean conflictsWith(Enchantment arg0) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public EnchantmentTarget getItemTarget() {
        // TODO Auto-generated method stub
        return EnchantmentTarget.WEAPON;
    }

    @Override
    public int getMaxLevel() {
        // TODO Auto-generated method stub
        return 10;
    }

    @Override
    public String getName() {
        // TODO Auto-generated method stub
        return "Backstab";
    }

    @Override
    public int getStartLevel() {
        // TODO Auto-generated method stub
        return 0;
    }
    
    

}
Код:
package ru.Trash.listeners;

import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.*********ventory.ItemStack;

import ru.Trash.main.Main;

public class BackstabListener implements Listener {
    
    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        Main.logger.info("[BACKSTAB LISTENER] "+event.getPlayer().getName()+" HAS JOINED");
        ItemStack item = new ItemStack(Material.WOOD_SWORD);
        item.addEnchantment(Main.BACKSTAB, 1);
        event.getPlayer().getInventory().addItem(item);
        event.getPlayer().updateInventory();
    }
    
    @EventHandler
    public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) {
        if(event.getDamager() instanceof Player) {
            Player p = (Player) event.getDamager();
            if(p.getItemInHand() != null && p.getItemInHand().getType() != Material.AIR) {
                Entity e = event.getEntity();
                if(p.getItemInHand().getItemMeta().hasEnchant(Main.BACKSTAB) && p.getLocation().getDirection().dot(e.getLocation().getDirection()) > 0) {
                    if(Math.random() <= 0.5){
                        e.sendMessage(ChatColor.RED + "[BACKSTAB LISTENER] Backstabbed");
                        p.sendMessage(ChatColor.GREEN + "[BACKSTAB LISTENER] Backstab");
                        event.setDamage(event.getDamage()*1.25);
                    }
                }
            }
        }
    }
}
 

Вложения

  • 1.png
    1.png
    647,8 КБ · Просмотры: 15
Последнее редактирование:
Если через гив всё выдаётся нормально - скорее всего, дело в команде энчант.
Подозреваю, что она реализована каким-нибудь эссентиалсом. А в нем жёсткие списки материалов, энчантов и всего прочего.
Короче говоря, для начала попробуй использовать /minecraft:enchant

А по поводу ошибки, что энчант уже зареган - всегда проверяй перед регистрацией наличие зачарования. Если есть - ничего делать не потребуется
 
Если через гив всё выдаётся нормально - скорее всего, дело в команде энчант.
Подозреваю, что она реализована каким-нибудь эссентиалсом. А в нем жёсткие списки материалов, энчантов и всего прочего.
Короче говоря, для начала попробуй использовать /minecraft:enchant

А по поводу ошибки, что энчант уже зареган - всегда проверяй перед регистрацией наличие зачарования. Если есть - ничего делать не потребуется

Проверка уже была, а /minecraft:enchant реагирует в точности так же, как и /enchant
(There is no such enchantment with ID 70)

Уже второй день пытаюсь решить данную проблему

Upd1. Если выдавать книгу, хранящую в себе зачарование, то стандартные зачарования работают корректно, а моим ничего нельзя зачаровать
 

Вложения

  • 2.png
    2.png
    350,1 КБ · Просмотры: 5
Последнее редактирование:
Код:
package Example.stack;
import java.lang.reflect.Field;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.*********ventory.ItemStack;
public class FaceEnchantment extends Enchantment {
    private NamespacedKey key;
    private int startLevel;
    private int maxLevel;
    public FaceEnchantment(NamespacedKey key, int startLevel, int maxLevel) {
        super(key);
        this.key = key;
        this.startLevel = startLevel;
        this.maxLevel = maxLevel;
        fix(this);
    }
    @Override
    public boolean canEnchantItem(ItemStack arg0) {
        return true;
    }
    @Override
    public boolean conflictsWith(Enchantment arg0) {
        return false;
    }
    @Override
    public EnchantmentTarget getItemTarget() {
        return null;
    }
    @Override
    public int getMaxLevel() {
        return maxLevel;
    }
    @Override
    public String getName() {
        return this.key.toString();
    }
    @Override
    public int getStartLevel() {
        return startLevel;
    }
    @Override
    public boolean isCursed() {
        return true;
    }
    @Override
    public boolean isTreasure() {
        return true;
    }
    private void fix(FaceEnchantment ench) {
        try {
            Field f = Enchantment.class.getDeclaredField("acceptingNew");
            f.setAccessible(true);
            f.set(null, true);
            Enchantment.registerEnchantment(ench);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
Последнее редактирование:
Код:
package Example.stack;

import java.lang.reflect.Field;

import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.*********ventory.ItemStack;

public class FaceEnchantment extends Enchantment {
    private NamespacedKey key;
    public FaceEnchantment(NamespacedKey key) {
        super(key);
        fix(this);
    }

    @Override
    public boolean canEnchantItem(ItemStack arg0) {
        return true;
    }

    @Override
    public boolean conflictsWith(Enchantment arg0) {
        return false;
    }

    @Override
    public EnchantmentTarget getItemTarget() {
        return null;
    }

    @Override
    public int getMaxLevel() {
        return 2;
    }

    @Override
    public String getName() {
        return this.key.toString();
    }

    @Override
    public int getStartLevel() {
        return 1;
    }

    @Override
    public boolean isCursed() {
        return false;
    }

    @Override
    public boolean isTreasure() {
        return false;
    }

    private void fix(FaceEnchantment ench) {
        try {
            Field f = Enchantment.class.getDeclaredField("acceptingNew");
            f.setAccessible(true);
            f.set(null, true);
            Enchantment.registerEnchantment(ench);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Попробовал, не получилось. Проблема не решилась
Upd1. Прикрепил вверху весь код
Upd2. Помогите пожалуйста :c
 
Последнее редактирование:
А что хоть пишет то? Я чёт не догоняю как может не чариться?
Быть может зачарование "отрезается", как если бы на одной книге были сила и острота - при зачаровании меча сила пропадет.
 
У него зачар ни с чем не конфликтует.
Пишет, что зачарование на книге, но с помощью наковальни нельзя зачаровать ничего.
Если таким же образом зачаровать на остроту, то можно зачаровать на наковальне
 
Попробуй ловить ивент зачара, и если на предмете есть зачар, меняй ему лор на Backstrap II
 
Попробуй ловить ивент зачара, и если на предмете есть зачар, меняй ему лор на Backstrap II
Меня больше волнует то, что нельзя зачаровать командой /enchant .
У меня уже был вариант, который работал с /enchant, но я не понял, почему команда перестала работать
 
Вот тебе решение для фейк чарок. Доделаешь там проверку, какие предметы можно чарить, какие нет.
Код:
    @EventHandler
    public void on(InventoryClickEvent e) {
        Inventory inv = e.getClickedInventory();
        if (inv == null) {
            return;
        }
        if (inv instanceof AnvilInventory) {
            if (isFaceEnchantment(inv.getItem(2))) {
                e.getWhoClicked().setItemOnCursor(inv.getItem(2));
                inv.clear();
                Player player = (Player) e.getWhoClicked();
                player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_USE, 1, 1);
            }
        }
    }

    @EventHandler
    public void on(PrepareAnvilEvent e) {
        ItemStack stack1 = e.getInventory().getItem(0);
        ItemStack stack2 = e.getInventory().getItem(1);
        if (isNull(stack1, stack2)) {
            return;
        }
        if (isFaceEnchantmentBook(stack2)) {
            ItemStack stack = stack1.clone();
            stack.addUnsafeEnchantments(stack2.getEnchantments());
            e.setResult(stack);
        }
    }

    public boolean isNull(ItemStack stack1, ItemStack stack2) {
        if (stack1 == null || stack2 == null) {
            return true;
        }
        return false;
    }

    public boolean isFaceEnchantmentBook(ItemStack stack2) {
        if (stack2.getType().equals(Material.ENCHANTED_BOOK)) {
            return isFaceEnchantment(stack2);
        }
        return false;
    }

    public boolean isFaceEnchantment(ItemStack stack) {
        if (stack == null) {
            return false;
        }
        Map<Enchantment, Integer> enchs = stack.getEnchantments();
        for (Entry<Enchantment, Integer> ench : enchs.entrySet()) {
            if (ench.getKey() instanceof FaceEnchantment) {
                return true;
            }
        }
        return false;
    }
 
Вот тебе решение для фейк чарок. Доделаешь там проверку, какие предметы можно чарить, какие нет.
Код:
    @EventHandler
    public void on(InventoryClickEvent e) {
        Inventory inv = e.getClickedInventory();
        if (inv == null) {
            return;
        }
        if (inv instanceof AnvilInventory) {
            if (isFaceEnchantment(inv.getItem(2))) {
                e.getWhoClicked().setItemOnCursor(inv.getItem(2));
                inv.clear();
                Player player = (Player) e.getWhoClicked();
                player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_USE, 1, 1);
            }
        }
    }

    @EventHandler
    public void on(PrepareAnvilEvent e) {
        ItemStack stack1 = e.getInventory().getItem(0);
        ItemStack stack2 = e.getInventory().getItem(1);
        if (isNull(stack1, stack2)) {
            return;
        }
        if (isFaceEnchantmentBook(stack2)) {
            ItemStack stack = stack1.clone();
            stack.addUnsafeEnchantments(stack2.getEnchantments());
            e.setResult(stack);
        }
    }

    public boolean isNull(ItemStack stack1, ItemStack stack2) {
        if (stack1 == null || stack2 == null) {
            return true;
        }
        return false;
    }

    public boolean isFaceEnchantmentBook(ItemStack stack2) {
        if (stack2.getType().equals(Material.ENCHANTED_BOOK)) {
            return isFaceEnchantment(stack2);
        }
        return false;
    }

    public boolean isFaceEnchantment(ItemStack stack) {
        if (stack == null) {
            return false;
        }
        Map<Enchantment, Integer> enchs = stack.getEnchantments();
        for (Entry<Enchantment, Integer> ench : enchs.entrySet()) {
            if (ench.getKey() instanceof FaceEnchantment) {
                return true;
            }
        }
        return false;
    }
Хах, попробовал сделать, версия Spigot'a 1.9
Выводил все зачарования, лежащие на книге в консоль. На картинке можно лицезреть, что при вложении в наковальню книги с кастомной чаркой вылетает "выход за границы", а при вложении остроты все происходит корректно

Upd1. При смене ID зачарования с зачарованной книги "слетает" зачарование
Upd2. С вами можно как-то связаться?
 

Вложения

  • 1.png
    1.png
    647,8 КБ · Просмотры: 13
Последнее редактирование:
Хах, попробовал сделать, версия Spigot'a 1.9
Выводил все зачарования, лежащие на книге в консоль. На картинке можно лицезреть, что при вложении в наковальню книги с кастомной чаркой вылетает "выход за границы", а при вложении остроты все происходит корректно

Upd1. При смене ID зачарования с зачарованной книги "слетает" зачарование
Upd2. С вами можно как-то связаться?
Попробуй для начала перестать быть динозавром и перейти на версию повыше. И попробуй регистрировать не из листа а просто создать класс и всё.
 
Там не все так просто оказалось. Хотфикс.

Код:
    @EventHandler
    public void on(InventoryClickEvent e) {
        Inventory inv = e.getClickedInventory();
        if (inv == null) {
            return;
        }
        if (inv instanceof AnvilInventory) {
            if (e.getSlot() == 2 && isFaceEnchantment(inv.getItem(2))) {
                e.getWhoClicked().setItemOnCursor(inv.getItem(2));
                inv.clear();
                Player player = (Player) e.getWhoClicked();
                player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_USE, 1, 1);
            }
        }
    }

    @EventHandler
    public void on(PrepareAnvilEvent e) {
        ItemStack stack1 = e.getInventory().getItem(0);
        ItemStack stack2 = e.getInventory().getItem(1);
        if (stack1!=null && isFaceEnchantmentBook(stack2)) {
            ItemStack stack = stack1.clone();
            stack.addUnsafeEnchantments(stack2.getEnchantments());
            e.setResult(stack);
            Player player = (Player) e.getViewers().get(0);
            player.updateInventory();
        }
        if (isFaceEnchantment(stack1)) {
            ItemStack result = e.getResult();
            if(result.getType().equals(Material.AIR)) {
                return;
            }
            for (Entry<Enchantment, Integer> ench : stack1.getEnchantments().entrySet()) {
                if (isFaceEnchantment(ench.getKey())) {
                    result.addUnsafeEnchantment(ench.getKey(), ench.getValue());
                }
            }
        }
    }

    public boolean isFaceEnchantmentBook(ItemStack stack2) {
        if (stack2 == null) {
            return false;
        }
        if (stack2.getType().equals(Material.ENCHANTED_BOOK)) {
            return isFaceEnchantment(stack2);
        }
        return false;
    }

    public boolean isFaceEnchantment(ItemStack stack) {
        if (stack == null) {
            return false;
        }
        Map<Enchantment, Integer> enchs = stack.getEnchantments();
        for (Entry<Enchantment, Integer> ench : enchs.entrySet()) {
            if (ench.getKey() instanceof FaceEnchantment) {
                return true;
            }
        }
        return false;
    }

    public boolean isFaceEnchantment(Enchantment ench) {
        if (ench instanceof FaceEnchantment) {
            return true;
        }
        return false;
    }
Вот эта затычка сохранит фейк чар после зачара обычной книгой и переименовании.
Действительно не понимаю. Никаких ошибок, просто нельзя зачаровать на наковальне и все
 
Поправил.
Код:
    @EventHandler
    public void on(PrepareAnvilEvent e) {
        AnvilInventory inv = e.getInventory();
        ItemStack stack1 = inv.getItem(0);
        ItemStack stack2 = inv.getItem(1);
        if (stack1!=null && isFaceEnchantmentBook(stack2)) {
            ItemStack stack = stack1.clone();
            EnchantmentStorageMeta meta = (EnchantmentStorageMeta) stack2.getItemMeta();
            stack.addUnsafeEnchantments(meta.getStoredEnchants());
            int cost = inv.getRepairCost();
            e.setResult(stack);
            if(cost==0) {
                inv.setRepairCost(1);
            }
        }
        if (isFaceEnchantment(stack1)) {
            ItemStack result = e.getResult();
            if(result.getType().equals(Material.AIR)) {
                return;
            }
            for (Entry<Enchantment, Integer> ench : stack1.getEnchantments().entrySet()) {
                if (isFaceEnchantment(ench.getKey())) {
                    result.addUnsafeEnchantment(ench.getKey(), ench.getValue());
                }
            }
        }
    }

    public boolean isFaceEnchantmentBook(ItemStack stack2) {
        if (stack2 == null) {
            return false;
        }
        if (stack2.getType().equals(Material.ENCHANTED_BOOK)) {
            EnchantmentStorageMeta meta = (EnchantmentStorageMeta) stack2.getItemMeta();
            Map<Enchantment, Integer> enchs = meta.getStoredEnchants();
            for (Entry<Enchantment, Integer> ench : enchs.entrySet()) {
                if (ench.getKey() instanceof FaceEnchantment) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean isFaceEnchantment(ItemStack stack) {
        if (stack == null) {
            return false;
        }
        Map<Enchantment, Integer> enchs = stack.getEnchantments();
        for (Entry<Enchantment, Integer> ench : enchs.entrySet()) {
            if (ench.getKey() instanceof FaceEnchantment) {
                return true;
            }
        }
        return false;
    }

    public boolean isFaceEnchantment(Enchantment ench) {
        if (ench instanceof FaceEnchantment) {
            return true;
        }
        return false;
    }
 
Последнее редактирование:
Пк не потянет
Поправил.
Код:
    @EventHandler
    public void on(PrepareAnvilEvent e) {
        AnvilInventory inv = e.getInventory();
        ItemStack stack1 = inv.getItem(0);
        ItemStack stack2 = inv.getItem(1);
        if (stack1!=null && isFaceEnchantmentBook(stack2)) {
            ItemStack stack = stack1.clone();
            EnchantmentStorageMeta meta = (EnchantmentStorageMeta) stack2.getItemMeta();
            stack.addUnsafeEnchantments(meta.getStoredEnchants());
            int cost = inv.getRepairCost();
            e.setResult(stack);
            if(cost==0) {
                inv.setRepairCost(1);
            }
        }
        if (isFaceEnchantment(stack1)) {
            ItemStack result = e.getResult();
            if(result.getType().equals(Material.AIR)) {
                return;
            }
            for (Entry<Enchantment, Integer> ench : stack1.getEnchantments().entrySet()) {
                if (isFaceEnchantment(ench.getKey())) {
                    result.addUnsafeEnchantment(ench.getKey(), ench.getValue());
                }
            }
        }
    }

    public boolean isFaceEnchantmentBook(ItemStack stack2) {
        if (stack2 == null) {
            return false;
        }
        if (stack2.getType().equals(Material.ENCHANTED_BOOK)) {
            EnchantmentStorageMeta meta = (EnchantmentStorageMeta) stack2.getItemMeta();
            Map<Enchantment, Integer> enchs = meta.getStoredEnchants();
            for (Entry<Enchantment, Integer> ench : enchs.entrySet()) {
                if (ench.getKey() instanceof FaceEnchantment) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean isFaceEnchantment(ItemStack stack) {
        if (stack == null) {
            return false;
        }
        Map<Enchantment, Integer> enchs = stack.getEnchantments();
        for (Entry<Enchantment, Integer> ench : enchs.entrySet()) {
            if (ench.getKey() instanceof FaceEnchantment) {
                return true;
            }
        }
        return false;
    }

    public boolean isFaceEnchantment(Enchantment ench) {
        if (ench instanceof FaceEnchantment) {
            return true;
        }
        return false;
    }
Спасибо, проблема решена
 
Назад
Верх