Bukkit How to change an int in the config file then be able to change it again without reloading (Custom config file class.))

五迷三道 提交于 2020-01-06 06:10:02

问题


Okay so I am making a custom feature for my OP-Prison server, one of the things that I need to do is get an integer from the players.yml file, check if it is >= one, if it is take away one, save it and then if it is still above one then they can repeat the action untill it's 0. The issue comes with the fact that I have to restart the server for the file to change, and even when I do, it will only go down by one integer at a time, before having to reload it again.

GUI Creation code:

Main main = Main.getPlugin(Main.class);

@SuppressWarnings("unused")
private FileControl fc;

@SuppressWarnings("unused")
private FileControl playerfc;

public static String inventoryname = Utils.chat(Main.pl.getFileControl().getConfig().getString("Backpacks.White.InventoryName"));

public List<Player> WhiteOpened = new ArrayList<>();

public static Inventory whiteBackpack(Player player) {
    Inventory whiteBackpack = Bukkit.createInventory(null, 27, (inventoryname));
    UUID uuid = player.getUniqueId();

    whiteBackpack.setItem(10,
            new ItemCreator(Material.INK_SACK).setData(8)
                    .setDisplayname(Utils.chat("&fCommon Packages &8» &f&l" + Main.pl.getPlayerFile().getConfig().getInt("Users." + uuid + ".Packages.Common")))
                    .getItem());

    return whiteBackpack;
}

Code for updating the config + item when the Commonpackage is clicked:

@EventHandler
public void whiteBackpackInteract(InventoryClickEvent event) {

    Player player = (Player) event.getWhoClicked();
    UUID uuid = player.getUniqueId();
    ItemStack clicked = event.getCurrentItem();
    String title = event.getInventory().getName();

    if (title.equals(inventoryname)) {
        // Making it so that the item cannot be moved
        event.setCancelled(true); 

        if (clicked != null) {

            if (event.getSlot() == 10) {

                // Getting the user's common packages section in the config and checking if it is greater than or equal to 1.
                if (Main.pl.getPlayerFile().getConfig().getInt("Users." + uuid + ".Packages.Common") >= 1) { 

                    // Saving the user's common package section to 'currentCommon'
                    Integer currentCommon = Main.pl.getPlayerFile().getConfig().getInt("Users." + uuid + ".Packages.Common");

                    // Taking away one from 'currentCommon' and saving it to 'newCommon'
                    Integer newCommon = currentCommon - 1;

                    // Getting the 'players.yml' file
                    File file = new File(main.getDataFolder(), "players.yml");
                    FileConfiguration config = YamlConfiguration.loadConfiguration(file);

                    // Checking if the current common keys is greater than or equal to 1
                    if (currentCommon >= 1) {
                        try {

                            //Now, Here's where the error lies.
                            //Gets the player's common package count and sets it to the 'newCommon' count
                            config.set("Users." + uuid + ".Packages.Common", newCommon);
                            //Saves the players.yml file
                            config.save(file);

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

                        // Updates the inventory they're currently in (Atleast it's meant to...)
                        player.updateInventory();
                        // Sends them a message (This is just for testing purposes, making sure it's working.)
                        player.sendMessage(Utils.chat("&8(&9Vexil&8) &fCommon Package"));
                    }
                }
            }
        }
    }
}

If there is any other code that you need, just ask I'll happily provide it for you.


回答1:


Right now, you need to restart the server for it to save the data to the file. This should not happen, since you are calling the method config.save(file). The following is simply speculation, but it's the only cause that I think can easily explain what is going on.

In the object that is returned by getPlayerFile().getConfig(), there is likely a variable that stores a FileConfiguration object. That variable houses all the data from the players.yml file. In your whiteBackpackInteract() method, you load the data all over again. You then continue on to write to this NEW FileConfiguration variable, rather than the one that is stored in getPlayerfile().getConfig(). Since you then proceed to save to the file directly, the variables stored in the getPlayerfile().getConfig() is never told that you changed some values around. To fix this, you need to change the following:

config.set("Users." + uuid + ".Packages.Common", newCommon);
config.save(file);

to this:

Main.pl.getPlayerFile().getConfig().set("Users." + uuid + ".Packages.Common", newCommon);
Main.pl.getPlayerFile().getConfig().save(file);

and then delete this line of code:

FileConfiguration config = YamlConfiguration.loadConfiguration(file);

This should solve your problem entirely. If it does not, I would recommend not using your friend's custom config API and instead just use the ones that are built in. Using third party code that you don't properly understand can very often lead to problems such as this.

The following are not the bugs, but are suggestions to help improve your code:

  • You should be sure to put your comments ABOVE or to the RIGHT over the code they describe. People read from top to bottom, so the comments (before I made the suggested edit to your post) were all below the code they describe.
  • Typically, you want to try to make sure that if code doesn't need to be run, it isn't. Since the int newCommon is not used until inside that if statement, you should move it in there.



回答2:


You are using Main.getPlugin();

Now while that doesn't seem like such a bad thing, your getting an unassigned variable, I have no idea how it is working but you're assigning Main to Main. There are 2 proper ways to actually get the main class.

The first, and generally best way, is to use dependency injection.

So basically,

public class Main extends JavaPlugin {

    @Override
    public void onEnable() {
        BackpackListener listener new Backpacklistener(this);
        getServer().getPluginManager().registerEvents(listener, this);
    }
}

public class BackpackListener implements Listener {
     private Main instance;
     private BackpackUtil util;

     public BackpackListener(Main instance) {
         this.instance = instance;
         util = new BackpackUtil();
     }

     @EventHandler
     public void onClick(InventoryClickEvent event) {
         //code
         util.whiteBackpack(instance);
     }
public class BackpackUtil {
    public Inventory whiteBackpack(Main instance) {
        FileConfiguration config = instance.getConfig();
        //Do things
        instance.saveConfig();
    }
}

The next way you can do it is less optimal, and frowned upon, but still an easier option.

public class Main() {
    public static Main instance;
    @Override
    public void onEnable() {
        instance = this;
    }
}

public class ConfigHelper() {
    Main instance = Main.instance;
    FileConfiguration config = instance.getConfig();
    //Do things
    instance.saveConfig();
}

It's good to get out of the habit of using the second method (It's called a singleton), because normally the main class will change, or have multiple instances, etc... but with Spigot there can only be one main instance and one thread.



来源:https://stackoverflow.com/questions/51250111/bukkit-how-to-change-an-int-in-the-config-file-then-be-able-to-change-it-again-w

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!