Java 如何使用getConfig()在主类之外的方法中编辑config.yml

Java 如何使用getConfig()在主类之外的方法中编辑config.yml,java,plugins,minecraft,bukkit,Java,Plugins,Minecraft,Bukkit,几天来,我一直有一个问题,再多的搜索也帮不了我解决。我最近才开始涉足Bukkit插件的开发,目前所有这些简单的插件都是设置加入/退出消息和AFK状态。然而,后一部分给了我一些问题 当玩家加入时,我的插口服务器控制台正在输出无法将event PlayerJoinEvent传递给ServerBasics,当玩家键入/afk时,在插件ServerBasics中执行命令“afk”时,未处理的异常 逻辑:Main类的onEnable()为AfkCommand设置命令执行器,为JoinListener设置事

几天来,我一直有一个问题,再多的搜索也帮不了我解决。我最近才开始涉足Bukkit插件的开发,目前所有这些简单的插件都是设置加入/退出消息和AFK状态。然而,后一部分给了我一些问题

当玩家加入时,我的插口服务器控制台正在输出无法将event PlayerJoinEvent传递给ServerBasics,当玩家键入/afk时,在插件ServerBasics中执行命令“afk”时,未处理的异常

逻辑:Main类的onEnable()为AfkCommand设置命令执行器,为JoinListener设置事件监听器,当玩家加入时,它的主要焦点是监视。此时,当玩家加入时,应该调用ToggleAFK中的toggle()方法,传递玩家的名称和一个假布尔值,以便在config.yml中为他们添加一个条目,并确保他们稍后键入/afk命令时,不使用afk。然后,ToggleAFK应使用afk保存配置。[player]等于false

同时,AfkCommand还应该使用播放器的名称和true/false参数调用ToggleAFK,并且ToggleAFK应该以相同的方式处理它。然而,它没有做到这一点

我在代码中设置了广播消息,以查看它何时失火。当播放机加入服务器时,JoinListener广播init和joined但不切换,而AfkCommand广播a、b和c但不切换,因此我们知道问题出在ToggleAFK中。TOGGLEFK不广播实例或g

问题似乎在于我创建了一个Main类的实例,但我不知道如何在另一个类中启用getConfig()命令,如果我所有的config.yml编辑都是在Main中处理的,那就一点也不整洁了。我已经读到主类不应该再次实例化,但我也发现了一个教程,其中它是以我在ToggleAFK中的方式实例化的,但是我的类不起作用(尽管在AfkCommand中这样做似乎很好)

我有什么选择?是否有不同于其他类的方式来编辑配置文件?我是否被迫在主目录中编辑它们?这个问题是因为ToggleAFK在Main之后被称为两个类而不是一个类吗?感谢您的帮助

我的主要班级:

package com.timothyreavis.serverbasics;

import org.bukkit.plugin.java.JavaPlugin;

public class Main extends JavaPlugin {

    @Override
    public void onEnable()
    {
        getCommand("afk").setExecutor(new AfkCommand(this));

        getServer().getPluginManager().registerEvents(new JoinListener(null), this);
    }

}
我的JoinListener类(当玩家加入时将afk设置为false。稍后我将对加入消息和内容进行软编码):

My ToggleAFK类(调用时应编辑config.yml文件):

和我的AfkCommand类(处理/afk并调用ToggleAFK):


据我所知,您的代码正确地将主插件类的引用传递给其他类的构造函数,并且似乎没有创建主插件类的新实例,因此应该没有任何障碍。当我测试代码时,无论是在玩家加入时还是在使用
/afk
命令时,都会抛出
NullPointerException
,因为
AfkCommand
JoinListener
类中的
afk
字段从未初始化

由于您的
JoinListener
类在其构造函数中将
ToggleAFK
对象作为参数,而不是像您的代码当前那样使用
new JoinListener(null)
初始化它(当到达
afk.toggle(player,false)
行时,会产生
NullPointerException
),我通过
newlistener(newtoggleafk(this))
将一个新的
ToggleAFK
对象传递给构造函数

设置
afk
字段的
AfkCommand
类的替代构造函数似乎从未使用过。您可以在这里初始化
afk
字段,方法是再次创建一个新的
ToggleAFK
对象,使用AfkCommand类的另一个构造函数(您在
onEnable()
方法中使用的)中已经提供的对主插件类的引用,如下所示:

Main plugin;
ToggleAFK afk;
public AfkCommand (Main instance) {
    plugin = instance;
    afk = new ToggleAFK(plugin);
}
这些更改似乎使代码按照我测试时的预期工作

需要注意的两件事:最好使用播放器的唯一ID(
player.getUniqueID()
)将播放器的AFK状态保存在配置文件中,因为现在
set
方法正在调用
player
对象上的
toString()
,这导致条目如下开头:
CraftPlayer{name=Steve}
。这不仅看起来很奇怪,而且使用了玩家的名字,这可能会改变。另外,将
切换
方法设置为静态并将其放置在
Util
类中可能更容易,这样您就不必创建
ToggleAFK
类的所有实例来访问该方法。这样的东西可能适合你:

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;

public class Util {

    private static Main plugin;

    public static void initialize(Main instance) {
        plugin = instance;
    }

    public static void toggleAFK(Player player, boolean isAFK) {
        if (plugin == null) {
            throw new IllegalStateException("This class has not been initialized yet!");
        }
        plugin.getConfig().set("AFK." + player.getUniqueId(), isAFK);
        plugin.saveConfig();

        String message = ChatColor.DARK_PURPLE + player.getName();
        message += (isAFK) ? " is now AFK." : " is no longer AFK.";
        Bukkit.broadcastMessage(message);
    }

}

对于这个特定的示例,您需要“初始化”
Util
类,最好是使用
Util.initialize(this)

oneable()方法中进行初始化!非常感谢你。我还将尝试合并您建议的更改。我试图在这里保持最佳实践,但同时我仍在摸索Bukkit插件。
Util
类是否可以用来转储我想在插件中的其他类之间引用的方法?很高兴它能工作!是的,我相信用任何经常重复使用的方法填充实用程序类是很常见的,这些方法也不需要从特定的对象/实例调用(因此这些方法是静态的)。
package com.timothyreavis.serverbasics;

import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
//import org.bukkit.event.player.PlayerMoveEvent;

public class AfkCommand implements CommandExecutor {
    // create Main class instance
    Main plugin;
    public AfkCommand (Main instance) {
        plugin = instance;
    }
    // create ToggleAFK class instance
    ToggleAFK afk;
    public AfkCommand (ToggleAFK instance) {
        afk = instance;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        Bukkit.broadcastMessage("a");
        if (sender instanceof Player) {
            Player player = (Player) sender;
            Bukkit.broadcastMessage("b");
            if (plugin.getConfig().getBoolean("afk."+sender) == false) {
                Bukkit.broadcastMessage("c");
                afk.toggle(player, true);
                Bukkit.broadcastMessage("d");
            } else {
                afk.toggle(player, false);
                Bukkit.broadcastMessage("d");
            }
        } else {
            Bukkit.broadcastMessage("e");
            return false;
        }
        // if command is used correctly, return true
        Bukkit.broadcastMessage("f");
        return true;
    }

}
Main plugin;
ToggleAFK afk;
public AfkCommand (Main instance) {
    plugin = instance;
    afk = new ToggleAFK(plugin);
}
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;

public class Util {

    private static Main plugin;

    public static void initialize(Main instance) {
        plugin = instance;
    }

    public static void toggleAFK(Player player, boolean isAFK) {
        if (plugin == null) {
            throw new IllegalStateException("This class has not been initialized yet!");
        }
        plugin.getConfig().set("AFK." + player.getUniqueId(), isAFK);
        plugin.saveConfig();

        String message = ChatColor.DARK_PURPLE + player.getName();
        message += (isAFK) ? " is now AFK." : " is no longer AFK.";
        Bukkit.broadcastMessage(message);
    }

}