Solved Saving/Loading HashMaps

Discussion in 'Plugin Development' started by Anrza, Jul 24, 2014.

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

    Anrza

    Yea, I'm sorry for posting a new thread about the subject, when there are already heaps of them, but I am really lost. I have a map
    Code:
    HashMap<String, Location> locationMap = new HashMap<String, Location>();
    that I want to save and load on disable and enable.
    Again, I'm sorry for asking this question that everyone has asked before.
     
  2. Offline

    Dragonphase

    Anrza

    Code:java
    1. config.set("locations", locationMap);
    2. (HashMap<String, Location>)config.get("locations");


    Also, it would be better to save only the X, Y, Z and World of the location instead of the entire Location. Unless you need all of the variables of the location saved.
     
  3. Offline

    Anrza

    Dragonphase
    Yea, thanks. I put getConfig.set("locations", locationMap); in my onDisable, but I'm not sure where to put line 2. Where I define the hashmap?
    Code:
    HashMap<String, Location> locationMap = (HashMap<String, Location>)getConfig.get("locations");
    And yea, I'll probably change it to X/Y/Z and world later.
     
  4. Offline

    Zettelkasten

    Anrza Put the second line in onEnable(). It will load the contents of the map. Also, you might want to add a test to check if it really is a map of Locations.
     
  5. Offline

    Dragonphase

    Anrza

    Save data in your onDisable method, and load data in your onEnable method, assuming your HashMap is a global HashMap<String, Location> inside your plugin's main class:

    Code:java
    1. private HashMap<String, Location> locationMap;
    2.  
    3. @Override
    4. public void onEnable(){
    5. locationMap = getConfig().contains("locations") ? (HashMap<String, Location>)getConfig().get("locations") : new HashMap<String, Location>();
    6. }
    7.  
    8. @Override
    9. public void onDisable(){
    10. getConfig().set("locations", locationMap);
    11. }
     
  6. Offline

    Anrza

    Dragonphase
    Thanks, but since locationMap is defined inside onEnable, it can't be accessed from anywhere else?
     
  7. Offline

    Dragonphase

    Anrza

    Declare locationMap in Class Level Scope like my previous post, as opposed to Method Scope.
     
  8. Offline

    mythbusterma

    You can't save a map like that unless all elements in it are wrapped primitives, strings, or objects that implement ConfigurationSerializable, which Location does not. You must create a way to serialize it, either by reimplementing location or translating it to and from a serializable form.
     
  9. Offline

    Dragonphase

    mythbusterma

    Which is why I suggested to him to create a class which contains only the data that he wants to save. I should have elaborated; I created a Position class which I use frequently for saving and loading locations. It implements ConfigurationSerializable.

    Just make sure that you register the class for serialization like so:

    Code:java
    1. static{
    2. ConfigurationSerialization.registerClass(Position.class);
    3. }
     
  10. Offline

    Anrza

    Dragonphase
    Gah... I don't get it... How do I solve my problem?
     
  11. Offline

    Dragonphase

    Anrza

    This might be useful. It explains the different types of scope levels in Java, but its' principles can be applied to virtually any Object-Oriented Programming language.
     
  12. Offline

    Anrza

    Dragonphase
    Ah, very useful.
    So, I have this:
    Code:
    HashMap<String, Location> locationMap;
       
        public void onEnable() {
            Bukkit.getServer().getPluginManager().registerEvents(this, this);
            @SuppressWarnings({ "unused", "unchecked" })
            HashMap<String, Location> locationMap = getConfig().contains("locations") ? (HashMap<String, Location>)getConfig().get("locations") : new HashMap<String, Location>();
        }
       
        public void onDisable() {
            getConfig().set("locations", locationMap);
        }
    But it doesn't work.
     
  13. Offline

    Dragonphase

    Anrza

    You're going to have to provide more information than "it doesn't work". Are there any errors? If so, show us a stack trace.
     
  14. Offline

    Anrza

    Dragonphase
    Code:
    org.bukkit.command.CommandException: Unhandled exception executing command 'setloc' in plugin Plugin v1.0
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:175) ~[craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at org.bukkit.craftbukkit.v1_7_R1.CraftServer.dispatchCommand(CraftServer.java:683) ~[craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.PlayerConnection.handleCommand(PlayerConnection.java:952) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.PlayerConnection.a(PlayerConnection.java:814) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.PacketPlayInChat.a(PacketPlayInChat.java:28) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.PacketPlayInChat.handle(PacketPlayInChat.java:47) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.NetworkManager.a(NetworkManager.java:146) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.ServerConnection.c(SourceFile:134) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.MinecraftServer.u(MinecraftServer.java:655) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.DedicatedServer.u(DedicatedServer.java:250) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.MinecraftServer.t(MinecraftServer.java:545) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.MinecraftServer.run(MinecraftServer.java:457) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        at net.minecraft.server.v1_7_R1.ThreadServerApplication.run(SourceFile:617) [craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
    Caused by: java.lang.NullPointerException
        at me.Anrza.Plugin.Plugin.onCommand(Plugin.java:94) ~[?:?]
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[craftbukkit-1.7.2-R0.3.jar:git-Bukkit-1.7.2-R0.3-b3020jnks]
        ... 13 more
    When I try to do anything with locationMap, setting/getting/checking.
     
  15. Offline

    Dragonphase

    Anrza

    You have a NullPointerException on line 94 in Plugin.java. Post your code.
     
  16. Offline

    Anrza

    Dragonphase
    Code:java
    1. package me.Anrza.Plugin;
    2.  
    3. import java.util.HashMap;
    4.  
    5. import org.bukkit.Bukkit;
    6. import org.bukkit.Location;
    7. import org.bukkit.command.Command;
    8. import org.bukkit.command.CommandSender;
    9. import org.bukkit.entity.Player;
    10. import org.bukkit.event.EventHandler;
    11. import org.bukkit.event.Listener;
    12. import org.bukkit.event.entity.EntityDamageByEntityEvent;
    13. import org.bukkit.event.entity.ProjectileLaunchEvent;
    14. import org.bukkit.event.player.PlayerJoinEvent;
    15. import org.bukkit.plugin.java.JavaPlugin;
    16.  
    17. public class Plugin extends JavaPlugin implements Listener{
    18.  
    19. HashMap<String, Location> locationMap;
    20.  
    21. public void onEnable() {
    22. Bukkit.getServer().getPluginManager().registerEvents(this, this);
    23. @SuppressWarnings({ "unused", "unchecked" })
    24. HashMap<String, Location> locationMap = getConfig().contains("locations") ? (HashMap<String, Location>)getConfig().get("locations") : new HashMap<String, Location>();
    25. }
    26.  
    27. public void onDisable() {
    28. getConfig().set("locations", locationMap);
    29. }
    30.  
    31. public boolean onCommand(CommandSender sender, Command cmd, String commandlabel, String[] args) {
    32.  
    33. if (!(sender instanceof Player)) {
    34. sender.sendMessage("This command cannot be used by the console.");
    35. return true;
    36. }
    37.  
    38. Player player = (Player) sender;
    39. Location loc = player.getLocation();
    40.  
    41. if (cmd.getName().equalsIgnoreCase("setLoc")) {
    42. if (args.length == 0) {
    43. player.sendMessage("Specify a location");
    44. return true;
    45. }
    46. String location = args[0];
    47. locationMap.put(location, loc) ;
    48. player.sendMessage("You set the location of " + location);
    49. return true;
    50. }
    51. if (cmd.getName().equalsIgnoreCase("getLoc")) {
    52. if (args.length == 0) {
    53. player.sendMessage("Specify a location");
    54. return true;
    55. }
    56. String location = args[0];
    57. if (!locationMap.containsKey(location)) {
    58. player.sendMessage("The specified location does not exist.");
    59. return true;
    60. } else {
    61. Location targetLoc = locationMap.get(location);
    62. player.teleport(targetLoc);
    63. player.sendMessage("You got the location of " + location);
    64. return true;
    65. }
    66. }
    67.  
    68. return true;
    69.  
    70. }
    71.  


    Shortened it a bit. Line 94 is 47 here.
     
  17. Offline

    Dragonphase

    Anrza

    You've got it wrong... in your onEnable, you're instantiating a new HashMap<String, Location>. This is method-scope, which means anything outside of this method will not be able to access that HashMap. You're not setting your global HashMap. Look at what I did at this post here. Also, as mythbusterma pointed out, Location doesn't implement ConfigurationSerializable, so you can't save it to a config.
     
  18. Offline

    Anrza

    Dragonphase
    I have no idea what you mean for me to look at.
     
  19. Offline

    Dragonphase

    Anrza

     
  20. Offline

    Anrza

    Dragonphase
    Sorry, I was unclear. I saw that, but I don't get what you want me to change.
    EDIT: I changed it to exactly what you wrote (except I had to put
    HashMap<String, Location> locationMap where you put locationMap
     
  21. Offline

    Dragonphase

    Anrza

    I really don't think you understand this at all... in your onEnable, you should NOT put this:

    Code:java
    1. HashMap<String, Location> locationMap ...


    if you DO put that, it will create a NEW instance of HashMap<String, Location> that will ONLY be accessible within the onEnable. Your GLOBAL locationMap, outside of your onEnable function, the one which looks like this:

    Code:java
    1. private HashMap<String, Location> locationMap;


    will remain uninitialised. In other words, it will be null, and when you try to access or modify it, you will receive a NullPointerException.
     
  22. Offline

    Anrza

    Dragonphase
    It gives me a red line under it if I do that:

    "locationMap cannot be resolved to a type"

    Dragonphase
    Code:java
    1. if (getConfig().contains("locations")) {
    2. System.out.println("debug");
    3. } else {
    4. System.out.println("noDebug");
    5. }


    I put that in my onEnable method, it says noDebug.

    And then I put it in my onDisable, it said debug. So it seems like it does save it, but it's removed when the plugin is restarted o.o

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 9, 2016
  23. Offline

    Anrza

    Oh, well, solved it using PogoStick29's video on it.
     
Thread Status:
Not open for further replies.

Share This Page