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

Spigot 1.8_R3起床战争插件商店背包物品扣除异常问题求助

Spigot背包物品指定数量扣除解决方案

现有代码问题分析

  1. 空指针错误原因:Inventory#getContents()返回的数组包含背包空槽位,对应值为null,遍历过程中未做非空判断直接调用invItem.getType()会触发NPE。
  2. 扣除逻辑错误:
    • 原Inventory#remove()方法仅能匹配完整相等的ItemStack(物品类型、数量、元数据完全一致),无法拆分堆叠扣除
    • 后续编写的逻辑未单独存储待扣除总数量,循环过程中修改待扣物品的amount属性导致计数混乱,且未覆盖堆叠数量刚好等于待扣数量的场景
    • 未提前校验玩家背包总资源是否足够,可能出现扣除一半资源后数量不足的异常情况

实现步骤

  1. 先读取待扣除的物品类型、总扣除数量
  2. 遍历玩家背包统计对应物品总数量,判断是否足够扣除,不足直接提示玩家终止操作
  3. 遍历背包槽位,对非空、类型匹配的物品堆叠进行扣除操作,单独用变量记录剩余待扣数量,扣完即终止循环
  4. 扣除完成后刷新玩家背包避免客户端显示异常

完整代码

public void removeItemFromInventory(Inventory inv, ItemStack currentItem, Player p) {
    // 读取配置获取待扣除的物品类型和总数量
    Material costType = getResource(Main.plugin.getConfigValue("shop." + currentItem.getTypeId() + ".type"));
    int totalCost = Integer.parseInt(Main.plugin.getConfigValue("shop." + currentItem.getTypeId() + ".cost"));

    // 第一步:先统计背包内对应物品总数量,判断是否足够
    int totalHas = 0;
    for (ItemStack invItem : inv.getContents()) {
        if (invItem != null && invItem.getType() == costType) {
            // 如果你的资源是自定义物品(带名称、lore),这里要加ItemMeta的匹配判断
            totalHas += invItem.getAmount();
        }
    }
    if (totalHas < totalCost) {
        p.sendMessage("§c资源不足,无法购买");
        return;
    }

    // 第二步:开始扣除物品
    int remainCost = totalCost;
    for (ItemStack invItem : inv.getContents()) {
        // 待扣数量为0直接终止循环
        if (remainCost <= 0) {
            break;
        }
        // 空槽、物品类型不匹配直接跳过
        if (invItem == null || invItem.getType() != costType) {
            continue;
        }
        // 自定义物品这里同样要加ItemMeta匹配判断
        int stackAmount = invItem.getAmount();
        if (stackAmount > remainCost) {
            // 当前堆叠数量大于剩余待扣数,直接减对应数量即可
            invItem.setAmount(stackAmount - remainCost);
            remainCost = 0;
        } else {
            // 当前堆叠数量小于等于待扣数,直接清空这个堆叠
            invItem.setAmount(0);
            remainCost -= stackAmount;
        }
    }

    // 刷新背包避免客户端显示不同步
    p.updateInventory();
    // 重新打开商店
    FastShop shop = new FastShop(p);
    p.closeInventory();
    p.openInventory(shop.getInventory());
}

注意事项

  • 如果你的服务器用的是带自定义名称、Lore的资源物品(比如改名为「铁」的铁锭),需要在类型判断的位置增加ItemMeta的相等判断,避免误扣普通铁锭
  • 1.8版本updateInventory()方法是有效的,高版本SpigotAPI可能需要调整背包刷新逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 12:45:08