如何使用 getConfig() 在 Main class 之外的方法中编辑 config.yml
How to use getConfig() to edit config.yml in a method outside of the Main class
几天来我一直遇到路径问题,没有任何搜索可以帮助我克服。我最近才开始涉足 Bukkit 插件开发,这个简单的插件当前所做的就是设置 join/quit 消息和 AFK 状态。但是,后一部分给我带来了问题。
我的 Spigot 服务器控制台正在输出 无法将事件 PlayerJoinEvent 传递给 ServerBasics 当玩家加入时 未处理的异常在插件 ServerBasics 中执行命令 'afk' 当玩家输入 /afk 时。
逻辑:Mainclass的onEnable()为AfkCommand设置命令执行器,为JoinListener设置事件监听器,主要是监听玩家加入。此时,它应该在玩家加入时调用 ToggleAFK 中的 toggle() 方法,传递玩家的名字和一个 false 布尔值以在 config.yml 中为他们添加一个条目并确保他们而不是 afk,应该他们稍后键入 /afk 命令。然后 ToggleAFK 应使用 afk.[player] 等于 false.
保存配置
同时,AfkCommand 也应该调用ToggleAFK 并带有玩家名称和true/false 参数,ToggleAFK 应该以同样的方式处理。然而,它并没有这样做。
我已经通过代码设置了广播消息,以查看它何时失败。当玩家加入服务器时,JoinListener 广播 init 和 joined 但不会 toggled,AfkCommand 广播 a、b 和 c 但不是 d,所以我们知道问题出在 ToggleAFK 中。 ToggleAFK 不广播 instanced 或 g.
问题似乎出在我创建 Main class 的实例上,但我不知道如何在另一个 class 中启用 getConfig() 命令,它不会如果我所有的 config.yml 编辑都在 Main 中处理,那就太整洁了。我读过 Main class 不应该再次实例化,但我还找到了一个教程,其中以我在 ToggleAFK 中完成它的方式实例化了它,但我的不起作用(尽管它当我在 AfkCommand 中这样做时似乎很好。
我有哪些选择?是否有不同于其他 classes 的不同方式来编辑配置文件?我是否被迫在 Main 中编辑它们?问题是因为 ToggleAFK 在 Main 之后被称为两个 classes 而不是一个?感谢任何帮助。
我的主class:
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 class(当玩家加入时将 afk 设置为 false。稍后我将对加入消息和内容进行软编码):
package com.timothyreavis.serverbasics;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import net.md_5.bungee.api.ChatColor;
public class JoinListener implements Listener
{
// create ToggleAFK class instance
ToggleAFK afk;
public JoinListener(ToggleAFK instance) {
afk = instance;
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event)
{
Bukkit.broadcastMessage("init");
// Player joins
Player player = event.getPlayer();
Bukkit.broadcastMessage("joined");
afk.toggle(player, false);
Bukkit.broadcastMessage("toggled");
// set player entry as not afk in config.yml
Bukkit.broadcastMessage("h");
if (!player.hasPlayedBefore()) {
// if player is new
event.setJoinMessage(ChatColor.DARK_PURPLE + "Welcome " + ChatColor.GREEN + event.getPlayer().getName() + ChatColor.DARK_PURPLE + " to the server!");
// tell player to read rules
event.getPlayer().sendMessage(ChatColor.YELLOW + "Hi, " + player.getName() + "! " + Bukkit.getServerName() + " is a rather unique server with custom plugins, so please read our rules and commands before getting started.");
} else {
// if player isn't new
event.setJoinMessage(ChatColor.GREEN + "[+] " + event.getPlayer().getName());
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event)
{
// Player quits
event.setQuitMessage(ChatColor.RED + "[-] " + event.getPlayer().getName());
}
}
我的 ToggleAFK class(这应该在调用时编辑 config.yml 文件):
package com.timothyreavis.serverbasics;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import net.md_5.bungee.api.ChatColor;
public class ToggleAFK {
// create Main class instance
Main plugin;
public ToggleAFK(Main instance) {
plugin = instance;
Bukkit.broadcastMessage("instanced");
}
public Boolean toggle(Player player, Boolean status) {
Bukkit.broadcastMessage("g");
plugin.getConfig().set("afk." + player, status);
plugin.saveConfig();
if (status) {
Bukkit.broadcastMessage(ChatColor.DARK_PURPLE + player.getName() + " is now AFK.");
} else {
Bukkit.broadcastMessage(ChatColor.DARK_PURPLE + player.getName() + " is no longer AFK.");
}
return true;
}
}
我的 AfkCommand class(处理 /afk 并调用 ToggleAFK):
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;
}
}
据我所知,您的代码正确地将主插件 class 的引用传递给其他 classes 的构造函数,并且似乎没有创建您的新实例主插件class,所以那里应该没有障碍。当我测试你的代码时,无论是当玩家加入还是使用 /afk
命令时,都会抛出 NullPointerException
,因为 AfkCommand
和 [=16= 中的 afk
字段] class 从未初始化。
由于您的 JoinListener
class 在其构造函数中将 ToggleAFK
对象作为参数,而不是像您的代码当前那样使用 new JoinListener(null)
初始化它(这会产生NullPointerException
当到达行 afk.toggle(player, false)
时),我使用 new Listener(new ToggleAFK(this))
.
将一个新的 ToggleAFK
对象传递给构造函数
您的 AfkCommand
class 的替代构造函数似乎从未使用过,该构造函数将设置 afk
字段。您可以在这里初始化 afk
字段,方法是再次创建一个新的 ToggleAFK
对象,这次使用对主插件 class 的引用已经在 AfkCommand class 的其他构造函数中提供(你在 onEnable()
方法中使用的那个),像这样:
Main plugin;
ToggleAFK afk;
public AfkCommand (Main instance) {
plugin = instance;
afk = new ToggleAFK(plugin);
}
这些更改似乎使代码按照我测试时的预期运行。
需要注意两点:最好使用玩家的唯一 ID (player.getUniqueID()
) 在配置文件中保存玩家的挂机状态,因为现在 set
方法正在调用 [= Player
对象上的 31=] 导致条目像这样开始:CraftPlayer{name=Steve}
。这不仅看起来很奇怪,而且使用了玩家的名字,这可能会改变。此外,将 toggle
方法设为静态并将其放在 Util
class 中可能更容易,这样您就不必创建 ToggleAFK
的所有实例class 访问该方法。这样的东西可能对你有用:
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);
}
}
对于这个具体示例,您需要 "initialize" Util
class,最好在您的 onEnable()
方法中使用 Util.initialize(this)
.
几天来我一直遇到路径问题,没有任何搜索可以帮助我克服。我最近才开始涉足 Bukkit 插件开发,这个简单的插件当前所做的就是设置 join/quit 消息和 AFK 状态。但是,后一部分给我带来了问题。
我的 Spigot 服务器控制台正在输出 无法将事件 PlayerJoinEvent 传递给 ServerBasics 当玩家加入时 未处理的异常在插件 ServerBasics 中执行命令 'afk' 当玩家输入 /afk 时。
逻辑:Mainclass的onEnable()为AfkCommand设置命令执行器,为JoinListener设置事件监听器,主要是监听玩家加入。此时,它应该在玩家加入时调用 ToggleAFK 中的 toggle() 方法,传递玩家的名字和一个 false 布尔值以在 config.yml 中为他们添加一个条目并确保他们而不是 afk,应该他们稍后键入 /afk 命令。然后 ToggleAFK 应使用 afk.[player] 等于 false.
保存配置同时,AfkCommand 也应该调用ToggleAFK 并带有玩家名称和true/false 参数,ToggleAFK 应该以同样的方式处理。然而,它并没有这样做。
我已经通过代码设置了广播消息,以查看它何时失败。当玩家加入服务器时,JoinListener 广播 init 和 joined 但不会 toggled,AfkCommand 广播 a、b 和 c 但不是 d,所以我们知道问题出在 ToggleAFK 中。 ToggleAFK 不广播 instanced 或 g.
问题似乎出在我创建 Main class 的实例上,但我不知道如何在另一个 class 中启用 getConfig() 命令,它不会如果我所有的 config.yml 编辑都在 Main 中处理,那就太整洁了。我读过 Main class 不应该再次实例化,但我还找到了一个教程,其中以我在 ToggleAFK 中完成它的方式实例化了它,但我的不起作用(尽管它当我在 AfkCommand 中这样做时似乎很好。
我有哪些选择?是否有不同于其他 classes 的不同方式来编辑配置文件?我是否被迫在 Main 中编辑它们?问题是因为 ToggleAFK 在 Main 之后被称为两个 classes 而不是一个?感谢任何帮助。
我的主class:
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 class(当玩家加入时将 afk 设置为 false。稍后我将对加入消息和内容进行软编码):
package com.timothyreavis.serverbasics;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import net.md_5.bungee.api.ChatColor;
public class JoinListener implements Listener
{
// create ToggleAFK class instance
ToggleAFK afk;
public JoinListener(ToggleAFK instance) {
afk = instance;
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event)
{
Bukkit.broadcastMessage("init");
// Player joins
Player player = event.getPlayer();
Bukkit.broadcastMessage("joined");
afk.toggle(player, false);
Bukkit.broadcastMessage("toggled");
// set player entry as not afk in config.yml
Bukkit.broadcastMessage("h");
if (!player.hasPlayedBefore()) {
// if player is new
event.setJoinMessage(ChatColor.DARK_PURPLE + "Welcome " + ChatColor.GREEN + event.getPlayer().getName() + ChatColor.DARK_PURPLE + " to the server!");
// tell player to read rules
event.getPlayer().sendMessage(ChatColor.YELLOW + "Hi, " + player.getName() + "! " + Bukkit.getServerName() + " is a rather unique server with custom plugins, so please read our rules and commands before getting started.");
} else {
// if player isn't new
event.setJoinMessage(ChatColor.GREEN + "[+] " + event.getPlayer().getName());
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event)
{
// Player quits
event.setQuitMessage(ChatColor.RED + "[-] " + event.getPlayer().getName());
}
}
我的 ToggleAFK class(这应该在调用时编辑 config.yml 文件):
package com.timothyreavis.serverbasics;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import net.md_5.bungee.api.ChatColor;
public class ToggleAFK {
// create Main class instance
Main plugin;
public ToggleAFK(Main instance) {
plugin = instance;
Bukkit.broadcastMessage("instanced");
}
public Boolean toggle(Player player, Boolean status) {
Bukkit.broadcastMessage("g");
plugin.getConfig().set("afk." + player, status);
plugin.saveConfig();
if (status) {
Bukkit.broadcastMessage(ChatColor.DARK_PURPLE + player.getName() + " is now AFK.");
} else {
Bukkit.broadcastMessage(ChatColor.DARK_PURPLE + player.getName() + " is no longer AFK.");
}
return true;
}
}
我的 AfkCommand class(处理 /afk 并调用 ToggleAFK):
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;
}
}
据我所知,您的代码正确地将主插件 class 的引用传递给其他 classes 的构造函数,并且似乎没有创建您的新实例主插件class,所以那里应该没有障碍。当我测试你的代码时,无论是当玩家加入还是使用 /afk
命令时,都会抛出 NullPointerException
,因为 AfkCommand
和 [=16= 中的 afk
字段] class 从未初始化。
由于您的 JoinListener
class 在其构造函数中将 ToggleAFK
对象作为参数,而不是像您的代码当前那样使用 new JoinListener(null)
初始化它(这会产生NullPointerException
当到达行 afk.toggle(player, false)
时),我使用 new Listener(new ToggleAFK(this))
.
ToggleAFK
对象传递给构造函数
您的 AfkCommand
class 的替代构造函数似乎从未使用过,该构造函数将设置 afk
字段。您可以在这里初始化 afk
字段,方法是再次创建一个新的 ToggleAFK
对象,这次使用对主插件 class 的引用已经在 AfkCommand class 的其他构造函数中提供(你在 onEnable()
方法中使用的那个),像这样:
Main plugin;
ToggleAFK afk;
public AfkCommand (Main instance) {
plugin = instance;
afk = new ToggleAFK(plugin);
}
这些更改似乎使代码按照我测试时的预期运行。
需要注意两点:最好使用玩家的唯一 ID (player.getUniqueID()
) 在配置文件中保存玩家的挂机状态,因为现在 set
方法正在调用 [= Player
对象上的 31=] 导致条目像这样开始:CraftPlayer{name=Steve}
。这不仅看起来很奇怪,而且使用了玩家的名字,这可能会改变。此外,将 toggle
方法设为静态并将其放在 Util
class 中可能更容易,这样您就不必创建 ToggleAFK
的所有实例class 访问该方法。这样的东西可能对你有用:
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);
}
}
对于这个具体示例,您需要 "initialize" Util
class,最好在您的 onEnable()
方法中使用 Util.initialize(this)
.