当前位置: 首页 > 知识库问答 >
问题:

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

史超英
2023-03-14

几天来,我在路径上遇到了一个持续存在的问题,再多的搜索也无法帮助我克服。我最近才开始涉足Bukkit插件开发,所有这些简单的插件当前所做的就是设置加入/退出消息和AFK状态。但是,后一部分给我带来了问题。

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

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

同时,AfkCommand也应该用玩家的名字和true/false参数调用togleAFK,togleAFK应该以同样的方式处理它。但是,它没有这样做。

我已经通过代码设置了广播消息,以查看它何时失灵。当播放器加入服务器时,JoinListener广播init并加入但不切换,AfkCommand广播a、b和c但不广播d,因此我们知道问题出在TokgleAFK中。TokgleAFK不广播实例化或g。

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

我有什么选择?是否有不同于其他类的编辑配置文件的方法?我是否被迫在主要部分编辑它们?问题是因为togglefk在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。稍后我将对加入消息和内容进行软编码):

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());
    }
}

我的Togglefk类(调用时应编辑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类(处理 /afk并调用TokgleAFK):

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;
    }

}

共有1个答案

墨寂弦
2023-03-14

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

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

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

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);
    }

}

对于这个特定的示例,您需要“初始化”< code>Util类,最好是在您的< code>onEnable()方法中使用< code > Util . initialize(this)。

 类似资料:
  • 问题内容: 当使用反射从另一个主要方法调用Java类的主要方法时, 我应该创建newInstance()还是直接调用main(),因为它是静态的。 问题答案: 对于您陈述的要求(动态地调用随机类的main方法,通过反射,您有很多不必要的代码。 您不需要为该类调用构造函数 您不需要内省类字段 由于您正在调用静态方法,因此甚至不需要真正的对象来调用该方法。 您可以修改以下代码来满足您的需求:

  • 我在这个上面有点卡住了。我正在编写一个包含两个类的java程序,然后是一个测试程序来测试类中的方法。我被困在主方法中调用下面的两个方法上。所有的类文件(测试程序类和另外两个类)都在编译,IDE没有给我任何错误消息,计算只是没有发生…… --主要方法代码: -账户类别代码: 注意:平衡设置器正在工作,因为它在测试程序的前面被调用... 非常感谢任何帮助!!! 账户类别的完整代码: 主要方法完整代码:

  • 我的作业是为一家正在补货的珠宝店计算税金和附加费,我遇到了一点小麻烦。我三次使用一种叫做calcExtraTax的方法来计算劳动率以及州税和联邦税。然后,我需要获取该方法的每个实例的结果,并将值传递给我的main方法中的适当变量。这是我的代码现在的样子(显然不完整): 我想弄清楚的是,我还需要在我的第二种方法中添加什么,以便每次都能够根据公式中使用的税率变量将结果传递到不同的税收成本变量中。

  • 我正试图做一个课堂作业,但我遇到了一个问题,我找不到解决方案。我的主方法中有一个变量,名为passwd。我让一个用户输入一个可能密码,输入被存储在变量中。然后检查password变量的长度,以确保它符合长度要求。然后我想让另一个方法chat检查变量的每个字符,看看它是否是一个数字。

  • 我是新的IntelliJ IDEA(使用2017.1.3)和gradle... Java文件: 建筑格拉德尔: 当我在Gradle Projects窗口中单击run任务时,我得到以下信息: 我如何设置Gradle或IntelliJ IDEA将主方法中的内容打印到IntelliJ IDEA的控制台视图? 真的不明白为什么控制台视图没有弹出(从IntelliJ IDEA内部,也为什么它没有显示错误是什