You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

1.8.8自定义Mending附魔插件无法生效问题求助

自定义Mending附魔插件失效排查(MC 1.8.8)

我首次开发插件,目标为1.8.8版本制作一个可通过/mending指令添加Mending附魔的插件。当前问题:使用/mending指令给钻石剑等物品附魔后,物品仅出现发光效果和NBT标签,但未实际应用自定义Mending附魔,获取XP时也无法修复耐久度。以下是插件的4个类代码:

主类(Mending2)

package me.marmosat.mending2;

import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;

public class Mending2 extends JavaPlugin implements Listener {
    public static final CustomMendingEnchantment mendingEnchant = new CustomMendingEnchantment(240);

    @Override
    public void onLoad() {
        // Register the custom Mending enchantment
        CustomMendingEnchantment.registerEnchantment(this.getLogger());
    }

    @Override
    public void onEnable() {
        // Register events
        getLogger().info("Mending2 plugin has been enabled!");
        getServer().getPluginManager().registerEvents(this, this);

        // Register the /mending command
        getCommand("mending").setExecutor(new MendingCommandExecutor(getLogger()));
    }

    @Override
    public void onDisable() {
        // Plugin shutdown logic
    }

    @EventHandler
    public void onPlayerExpChange(PlayerExpChangeEvent event) {
        // Check if player has Mending enchanted items
        for (ItemStack item : event.getPlayer().getInventory().getContents()) {
            if (item != null && item.containsEnchantment(CustomMendingEnchantment.getCustomMendingEnchantment())) {
                // Calculate repair cost based on damage
                int repairCost = calculateRepairCost(item);

                // Deduct repair cost from player's experience
                if (event.getAmount() >= repairCost) {
                    event.setAmount(event.getAmount() - repairCost);

                    // Repair the item
                    repairItem(item);
                }
            }
        }
    }

    private int calculateRepairCost(ItemStack item) {
        // Calculate repair cost based on damage
        int maxDurability = item.getType().getMaxDurability();
        int durability = maxDurability - item.getDurability();
        double repairCostPercentage = 0.2; // Example: 20% repair cost per durability point
        return (int) Math.ceil(durability * repairCostPercentage);
    }

    private void repairItem(ItemStack item) {
        // Repair the item by setting its durability to its maximum
        item.setDurability((short) 0);
    }
}

CustomMendingEnchantment类

package me.marmosat.mending2;

import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.inventory.ItemStack;
import java.util.logging.Logger;
import java.lang.reflect.Field;

public class CustomMendingEnchantment extends Enchantment {

    private static boolean registered = false;
    private static Logger logger;
    private static CustomMendingEnchantment instance;

    // Constructor
    public CustomMendingEnchantment(int id) {
        super(id);
    }

    // Static method to register the custom enchantment
    public static void registerEnchantment(Logger pluginLogger) {
        logger = pluginLogger;
        instance = new CustomMendingEnchantment(240);
        try {
            Field acceptingNewField = Enchantment.class.getDeclaredField("acceptingNew");
            acceptingNewField.setAccessible(true);
            acceptingNewField.set(null, true); // Allow registering new enchantments

            Enchantment.registerEnchantment(instance);
            logger.info("Custom Mending enchantment registered!");
            registered = true;
        } catch (Exception e) {

            // Failed to register the enchantment
            logger.severe("Failed to register custom Mending enchantment!");
        }
    }

    // Static method to get the custom enchantment instance
    public static CustomMendingEnchantment getCustomMendingEnchantment() {
        if (instance == null) {
            // If the enchantment is not registered, return null
            logger.warning("Custom Mending enchantment has not been registered!");
        }
        return instance;
    }
    // Method to check if the enchantment is registered
    public static boolean isRegistered() {
        return registered;
    }

    // Implementing abstract method getName() from Enchantment
    @Override
    public String getName() {
        return "Mending"; // Set the name of the enchantment
    }

    // Implementing abstract method getMaxLevel() from Enchantment
    @Override
    public int getMaxLevel() {
        return 1; // Set the maximum level of the enchantment
    }

    // Implementing abstract method getStartLevel() from Enchantment
    @Override
    public int getStartLevel() {
        return 1; // Set the starting level of the enchantment
    }

    // Implementing abstract method getItemTarget() from Enchantment
    @Override
    public EnchantmentTarget getItemTarget() {
        return EnchantmentTarget.BREAKABLE; // Specify the item target for the enchantment
    }

    // Implementing abstract method isTreasure() from Enchantment
    @Override
    public boolean isTreasure() {
        return false; // Indicate whether the enchantment is considered a treasure enchantment
    }

    // Implementing abstract method isCursed() from Enchantment
    @Override
    public boolean isCursed() {
        return false; // Indicate whether the enchantment is considered a curse
    }

    // Implementing abstract method conflictsWith(Enchantment) from Enchantment
    @Override
    public boolean conflictsWith(Enchantment other) {
        // Indicate whether this enchantment conflicts with another enchantment
        return false; // Mending does not conflict with other enchantments
    }

    // Implementing abstract method canEnchantItem(ItemStack) from Enchantment
    @Override
    public boolean canEnchantItem(ItemStack item) {
        // Return true if the item can be enchanted with this enchantment
        return true; // Can enchant any item
    }

    // Implementing other Enchantment methods as needed
}

MendingCommandExecutor类

package me.marmosat.mending2;

import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import java.util.logging.Logger;

public class MendingCommandExecutor implements CommandExecutor {

    private final Logger logger;

    // Constructor with Logger parameter
    public MendingCommandExecutor(Logger logger) {
        this.logger = logger;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        // Check if the sender is a player
        if (!(sender instanceof Player)) {
            sender.sendMessage("This command can only be executed by players.");
            return false;
        }

        Player player = (Player) sender;

        // Check if the player has permission to use the command
        if (!player.isOp()) {
            sender.sendMessage("You do not have permission to use this command.");
            return false;
        }

        try {
            // Get the item the player is currently holding in the main hand
            ItemStack heldItem = player.getInventory().getItemInHand(); // Deprecated in newer versions, but still usable in 1.8.8

            // Check if the held item is not air
            if (heldItem != null && heldItem.getType() != Material.AIR) {
                // Apply the Mending enchantment to the held item
                if (CustomMendingEnchantment.isRegistered()) {
                    heldItem.addUnsafeEnchantment(CustomMendingEnchantment.getCustomMendingEnchantment(), 1);
                    player.sendMessage("The item in your hand now has the Mending enchantment.");
                } else {
                    player.sendMessage("An error occurred while executing the command.");
                    logger.severe("Custom Mending enchantment is not registered.");
                }
            } else {
                player.sendMessage("You are not holding any item.");
            }
            return true;
        } catch (Exception e) {
            // Handle any exceptions
            sender.sendMessage("An error occurred while executing the command.");
            logger.severe("Error while executing /mending command: " + e.getMessage());
            return false;
        }
    }
}

MendingListener类

package me.marmosat.mending2;

import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.bukkit.inventory.ItemStack;

public class MendingListener implements Listener {

    @EventHandler
    public void onPlayerExpChange(PlayerExpChangeEvent event) {
        // Check if player has Mending enchanted items
        for (ItemStack item : event.getPlayer().getInventory().getContents()) {
            if (item != null && item.containsEnchantment(CustomMendingEnchantment.getCustomMendingEnchantment())) {
                // Calculate repair cost based on damage
                int repairCost = calculateRepairCost(item);

                // Deduct repair cost from player's experience
                if (event.getAmount() >= repairCost) {
                    event.setAmount(event.getAmount() - repairCost);

                    // Repair the item
                    repairItem(item);
                }
            }
        }
    }

    private int calculateRepairCost(ItemStack item) {
        // Calculate repair cost based on damage
        int maxDurability = item.getType().getMaxDurability();
        int durability = maxDurability - item.getDurability();
        double repairCostPercentage = 0.2; // Example: 20% repair cost per durability point
        return (int) Math.ceil(durability * repairCostPercentage);
    }

    private void repairItem(ItemStack item) {
        // Repair the item by setting its durability to its maximum
        item.setDurability((short) 0);
    }

}

问题排查与修复方案

1. 附魔实例不一致

主类中定义了mendingEnchant静态实例,但CustomMendingEnchantment的注册方法又新建了instance实例,导致指令添加的附魔和监听器检查的附魔不是同一个对象,自然无法触发修复逻辑。
修复:删除主类中的public static final CustomMendingEnchantment mendingEnchant = new CustomMendingEnchantment(240);,全程使用CustomMendingEnchantment.getCustomMendingEnchantment()获取唯一实例。

2. 监听器冗余与冲突

主类已经实现Listener并注册了PlayerExpChangeEvent处理逻辑,同时存在重复的MendingListener类,两者逻辑完全一致,可能导致监听器触发异常。
修复:删除MendingListener类,或者在主类onEnable()中注册该监听器(二选一,推荐删除冗余类)。

3. 耐久计算与修复逻辑错误

  • calculateRepairCost方法中,int durability = maxDurability - item.getDurability();计算的是剩余耐久,而我们需要的是已损耗的耐久(需要修复的点数),1.8.8中item.getDurability()返回的就是已损耗值,正确计算应为:
    int damagedPoints = item.getDurability();
    
  • repairItem直接将耐久设为0,不符合Mending逐步修复的逻辑,且会导致一次XP直接修满所有耐久,正确逻辑应为根据消耗的XP修复对应点数:
    private void repairItem(ItemStack item, int repairAmount) {
        // 确保修复后耐久不低于0
        int newDurability = Math.max(0, item.getDurability() - repairAmount);
        item.setDurability((short) newDurability);
    }
    
  • XP消耗比例调整:参考原版Mending,1点XP修复2点耐久,对应修改calculateRepairCost方法,比如1点耐久消耗0.5XP,向上取整。

4. 客户端同步问题

修改物品耐久后,需要通知客户端更新物品状态,否则客户端看不到耐久变化,在修复后添加:

event.getPlayer().updateInventory();

5. 附魔类优化

将CustomMendingEnchantment的构造函数改为private,避免外部随意创建实例,确保只有注册方法生成的唯一实例被使用:

private CustomMendingEnchantment(int id) {
    super(id);
}

内容的提问来源于stack exchange,提问作者marmosat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 15:49:52