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

Bukkit插件跨文件调用非static方法loadHeadTextures失效求助

解决Bukkit插件跨文件调用非static方法无效的问题

问题根源

你的代码存在两个核心问题:

  1. 调用顺序错误:主类Grillade的onEnable方法里,先调用AnvilListener的loadHeadTextures,再执行checkFiles创建heads.json文件。此时调用loadHeadTextures时文件还未生成,方法触发if (!jsonFile.exists())直接返回,没有加载任何数据。
  2. 重复加载冗余:AnvilListener的事件处理方法中每次触发都调用loadHeadTextures,既浪费资源,也掩盖了主类调用无效的问题——事件触发时插件已完成初始化,文件已存在,所以能正常加载。

修复方案

1. 调整主类调用顺序

优先执行文件检查创建逻辑,确保heads.json存在后再加载纹理数据:

@Override
public void onEnable() {
    instance = this;

    checkFiles(); // 先创建必要文件
    AnvilListener anvilListener = new AnvilListener();
    anvilListener.loadHeadTextures(); // 此时文件已存在,可正常加载

    getServer().getPluginManager().registerEvents(anvilListener, this);
    getLogger().info("Grillade Plugin Operational!");
}

2. 移除事件中的重复加载

事件处理无需每次重新加载纹理,只保留初始化阶段的一次加载即可:

@EventHandler
public void onAnvilPrepare(PrepareAnvilEvent event) {
    // 移除此处的loadHeadTextures调用
    AnvilInventory anvilInventory = event.getInventory();
    ItemStack[] contents = anvilInventory.getContents();

    ItemStack firstInput = contents[0];
    ItemStack secondInput = contents[1];
    String renameText = event.getInventory().getRenameText();

    List<Material> classicHeads = new ArrayList<>();
    classicHeads.add(Material.CREEPER_HEAD);
    classicHeads.add(Material.SKELETON_SKULL);
    classicHeads.add(Material.ZOMBIE_HEAD);

    if (firstInput != null && secondInput == null && classicHeads.contains(firstInput.getType()) &&
            renameText != null && headTextures.containsKey(renameText)) {

        String texture = headTextures.get(renameText);
        ItemStack customHead = createCustomHead(texture, renameText);
        event.setResult(customHead);
    }
}

3. 优化纹理加载方法(可选)

如果后续需要支持热重载纹理,可在加载前清空旧数据,避免重复键值:

public void loadHeadTextures() {
    File jsonFile = new File(Grillade.getInstance().getDataFolder(), "heads.json");
    Bukkit.broadcastMessage("正在加载头颅纹理");

    if (!jsonFile.exists()) {
        return;
    }

    headTextures.clear(); // 清空旧数据,防止重复加载
    try {
        FileReader reader = new FileReader(jsonFile);
        JsonElement jsonElement = JsonParser.parseReader(reader);
        JsonObject jsonObject = jsonElement.getAsJsonObject();
        JsonArray headsArray = jsonObject.getAsJsonArray("heads");

        for (JsonElement headElement : headsArray) {
            JsonObject headObject = headElement.getAsJsonObject();
            String name = headObject.get("name").getAsString();
            String texture = headObject.get("texture").getAsString();

            headTextures.put(name, texture);
        }

        reader.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

验证效果

修改后,插件启用时会先创建heads.json(若不存在),再加载纹理数据,事件处理时直接使用已加载的headTextures映射,既解决了主类调用无效的问题,也提升了事件处理效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:35:21