Solved Hashmap not properly saving on /reload

Discussion in 'Plugin Development' started by pers2981, Apr 12, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    pers2981

    Hey there,

    So recently i've been playing around with saving/loading player data from a hashmap to a config file dedicated to that player. I've created two functions.

    loadData(player) (open)

    Code:
    public void loadData(Player player)
    {
    try
    {
    File userFile = new File("plugins" + File.separator + "MinecraftLegend" + File.separator + "users" + File.separator + player.getDisplayName() + ".yml");
    FileConfiguration config = getConfig();
     
    if (!userFile.exists())
    {
    System.out.println(player.getDisplayName() + " user file created.");
    Bukkit.broadcastMessage(ChatColor.GREEN + "[Server] " + ChatColor.WHITE + "Welcome to the server " + player.getDisplayName() + "!");
     
    config.set("stats.gold", 100);
    config.set("stats.class", 1);
    config.save(userFile);
    // Setup default values and save it to file.
    }
     
    // Load data from file to hashmap.
     
    PlayerMoney.remove(player.getDisplayName());
    PlayerClass.remove(player.getDisplayName());
     
    PlayerMoney.put(player.getDisplayName(),config.getInt("stats.gold"));
    System.out.println("Loaded " + config.getInt("stats.gold"));
    PlayerClass.put(player.getDisplayName(),config.getInt("stats.class"));
     
    }catch(Exception e)
    {
    System.out.println("Error " + e);
    }
    }
    

    And
    saveData(player) (open)

    Code:
    public void saveData(Player player)
    {
    try
    {
    // Save data from hashmap to file.
    File userFile = new File("plugins" + File.separator + "MinecraftLegend" + File.separator + "users" + File.separator + player.getDisplayName() + ".yml");
    FileConfiguration config = getConfig();
     
    config.set("stats.gold", PlayerMoney.get(player.getDisplayName()));
    config.set("stats.class", PlayerClass.get(player.getDisplayName()));
    System.out.println("Saved " + PlayerMoney.get(player.getDisplayName()));
    config.save(userFile);
     
    PlayerMoney.remove(player.getDisplayName());
    PlayerClass.remove(player.getDisplayName());
     
    }catch(Exception e)
    {
    System.out.println("Error " + e);
    }
    }
    


    I call these functions when a player leaves/enters the server and when the plugin loads/unloads, everything works fine and dandy when the player leaves/enters, but I encounter an error when the plugin loads/unloads. After spending countless hours trying to fix this problem, i'm stuck.

    I would greatly appreciate if anyone could aid me in fixing this problem.

    I don't receive any errors, simply the file loses it's value (resets to zero).

    Warm regards,
    Jacob
     
  2. Offline

    mcoder

    I'm not 100% sure if that's the problem, but you should use player.getName() instead of player.getDisplayName(). While getDisplayName() returns the current name as shown in chat (including all prefixes), which can change depending on what plugins are currently loaded/unloaded. A plugin changing those might not yet be loaded on startup and therefore, your plugin can't find the appropriete file. If you use getName(), it will return just the actual name, which (usually) always stays the same.
     
  3. Offline

    pers2981

    You're right, I should use .getName(), but that can't be the issue considering only my plugin is running, and it doesn't tamper with display names.
     
  4. Offline

    mcoder

    All right. Which class is that code in? is it your main plugin class? And what exactly does getConfig() return? is it the inherited method in your main plugin class? or did you write that yourself?

    The problem i see is, that you create a new file for the player. In the next line you get a config file from your getConfig() method, and then you use this config to do all of your saving/loading. The file you created ("userFile") before is never used, and therefore can't contain any information.
     
  5. Offline

    pers2981

    Everything is in the main class. The getConfig() method is apart of the configFile class, I did not write the method, it returns a value from a config file. In this case, it returns the money and class values from username.yml

    Here is what happens.
    If a config file for the player doesn't exist then it will make one, and set it to the default values.
    The values will then be read from the players config file and assigned to a hashmap.


    That would make sense but why would it work when a player leave / joins but mess up when the server reloads?
     
  6. Offline

    mcoder

    It does not work in either cases. When the server reloades, all Objects (including your HashMaps) are "deleted" and therefore you would have to reload all data from a file. When a player simply disconnects, the HashMap stays intact and on reconnect still has the same value. The getConfig() method actually returns a config file. But not just any, but THE config file for your plugin, the config.yml in your plugins directory. Unless rewritten, it can never return your player data file.
     
  7. Offline

    pers2981

    Oh yes, sorry. My bad, I was replying through my phone. You're correct. I misunderstood what you where asking. I meant to say 'config.getInt("stats.gold")' returns the value of gold from the config file. Also, I remove the data from the hashmap when a player leaves the game.

    Here is how the 'Load' method works.
    Make sure any existing hashmaps don't contain any of this players data. If they do, remove it. If username.yml exists, then read it and assign it's values to a hashmap. If it doesn't exist, create username.yml, assign it's values to that of default and save the file. Open username.yml and throw it's contents into multiple hashmap(s). E.x PlayerMoney, PlayerClass etc.

    Here is how the 'Save' method works.
    Grab the players data from the hashmaps and write it to username.yml. Remove the players data from the hashmaps.

    Once again, still confused as to why one works, and the other doesn't. It's all the same code.
     
  8. Offline

    mcoder

    this part ist supposed to load teh data from the user file correct?

    the way you have it right now is, it loads from "config" which is the FileConfiguration returned by getConfig(). That is the default config. So you are always loading your data from the config, no matter if the file exists or not.

    this is the part where you initialise the new file with your default values. But again, "config" is your default file configuration, so you are setting the values in your config.yml over and over again, but never in the new file.


    change this to something like

    Code:java
    1.  
    2. File userFile = new File("plugins" + File.separator + "MinecraftLegend" + File.separator + "users" + File.separator + player.getDisplayName() + ".yml");
    3. FileConfiguration config =
    4. YamlConfiguration.loadConfiguration(userFile);
    5.  


    Of course you would have to check if userFile actually exists before giving it as argument to a config.
     
    pers2981 likes this.
  9. Offline

    pers2981

    Thank you so much for all the help, you did not only fix my problem but explained in detail why it wasn't working. I am very grateful.
     
  10. Offline

    mcoder

    I'm glad I could help :)
     
  11. Offline

    bobnixon1

    How do I create the file if it doesn't exsist?
     
Thread Status:
Not open for further replies.

Share This Page