Solved Saving/Loading <String, Integer> Hashmaps

Discussion in 'Plugin Development' started by icewhisker, Dec 1, 2013.

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

    icewhisker

    ok I am completely rewriting this, I want to be able to store materials in an arraylist (Done) and then save them so that when I reload and restart the server, It doesn't reset them all. I was thinking I could store the arraylist in a .txt or a .yml file but I don't know how I would put it into there and how to get the information back out. I also want to set a number that can change for each of the material without having to make a variable for each one (Because there are hundreds).

    What I am wanting this to do in the plugin for players to 'donate' blocks, items, armour, and enchanted gear to the server and the server keeps a record of how much of each material has been donated in a whole not how much has been donated by each player. I then want it to be able to show that through a minecraft book, or a sign or something

    ok I fixed the seconds error, the one that means that the same thing can be stored in the arraylist by adding:

    if (items.contains(item)) {
    player.sendMessage(ChatColor.RED + "This item has already been loaded");
    }
    else if (!items.contains(item)) {
    items.add(item);
    player.sendMessage(ChatColor.GREEN + "Items loaded: " + items);

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

    icewhisker

    bump and I have figured out a way of putting the arralist (now changed to a list) into a config file, but I cannot reach it again to get back out, If someone could please help it would be really great. I want to be able to link a material with an integer in another arraylist, or some easier way of doing it.
     
  3. Offline

    Not2EXceL

    post your save code. and we could be more help
     
  4. Offline

    icewhisker

    ok sure here is my main:
    Code:
    package icewhisker.bb;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.configuration.file.FileConfiguration;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class BB extends JavaPlugin{
        
        static int number = 1;
        
        @Override
        public void onEnable() {
            Bukkit.getServer().getPluginManager().registerEvents(new SignCreate(this), this);
            Bukkit.getServer().getPluginManager().registerEvents(new Collection(this), this);
            Bukkit.getServer().getPluginManager().registerEvents(new Sending(this), this);
            }
        
        public static List<String> items = new ArrayList<String>();
        
        @Override
        public void onDisable() {
            FileConfiguration cfg = getConfig();
            cfg.addDefault("BlockBank.materialsLoaded", items);
            cfg.options().copyDefaults(true);
            saveDefaultConfig(); 
            saveConfig();
            
        }
        
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        Player player = (Player)sender;
        
            if (cmd.getName().equalsIgnoreCase("collection")) {
                if (player.getName().equalsIgnoreCase("icewhisker")) {
                    if (args.length == 0) {
                        player.sendMessage(ChatColor.RED + "Please specify a number");
                    }
                        
                    else if (args.length == 1) {
                        number = Integer.parseInt(args[0]);
                            
                        if (number > 0)
                            player.sendMessage(ChatColor.BLUE + "Collection rate: " + number);
                            
                        else if (number > 64) {
                            player.sendMessage(ChatColor.RED + "Please use a number less then 65");
                            
                        }
                            
                        else if (number <= 0) {
                            player.sendMessage(ChatColor.RED + "Please use a number higher then 0");
                        }
                    }
                }
            }
            return true;
        }
    }
    
        
    
    here is my collection class (for collecting the materials, still works):
    Code:
    package icewhisker.bb;
    
    import icewhisker.bb.BB;
    
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.block.Sign;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.ItemStack;
    
    public class Collection implements Listener{
        
          BB plugin;
          
          Collection(BB main) {
              this.plugin = main;
          } 
    
        @SuppressWarnings("deprecation")
        @EventHandler
          public void onPlayerInteract(PlayerInteractEvent event) {
          Player player = event.getPlayer();
            if (event.getAction() == Action.RIGHT_CLICK_BLOCK && (event.getClickedBlock().getType() == Material.WALL_SIGN)) {
                Sign s = (Sign)event.getClickedBlock().getState();
                if (player.getName().equalsIgnoreCase("icewhisker") && (player.hasPermission("blockbank.grabresources"))) {
                    if ((player.getItemInHand() == null) || (player.getItemInHand().getType() == Material.AIR)) {
                        if (s.getLine(0).equalsIgnoreCase(ChatColor.GOLD + "[Stored]") && !s.getLine(1).equalsIgnoreCase("")) {
                            Material item = Material.valueOf(s.getLine(1));
                            if (BB.number <= Sending.max) {
                                player.getInventory().addItem(new ItemStack[] { new ItemStack(item, BB.number) });
                                player.updateInventory();
                                player.sendMessage("You got " + BB.number + " " + item.toString().toLowerCase());    
                            }
                            else if (BB.number < Sending.max) {
                                player.sendMessage("There isn't enough " + item.toString().toLowerCase());
                            }
                        }
                    }
                    else {
                        player.sendMessage(ChatColor.RED + "Please use without an item in hand");
                    }
                }
                else if (!(player.getName().equalsIgnoreCase("icewhisker"))) {
                    player.sendMessage("You are not the admin of this server!");
                }
            }
        }
    }
    
    
    this is for loading the materials into the config:
    Code:
    package icewhisker.bb;
    
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.block.Sign;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.PlayerInteractEvent;
    
    public class Sending implements Listener{
        
        BB plugin;
          
          Sending(BB main) {
              this.plugin = main;
          } 
        
        public static int max = 50;
        
        @EventHandler
        public void arrayList(PlayerInteractEvent event) {
            Player player = event.getPlayer();
            if (event.getAction() == Action.RIGHT_CLICK_BLOCK && (event.getClickedBlock().getType() == Material.WALL_SIGN)) {
                Sign s = (Sign)event.getClickedBlock().getState();
                if (s.getLine(0).equalsIgnoreCase(ChatColor.GOLD + "[Load]")) {
                    String item = String.valueOf(s.getLine(1).toString());
                    if (BB.items.contains(item)) {
                        player.sendMessage(ChatColor.RED + "This item has already been loaded");
                    }
                    else if (!BB.items.contains(item)) {
                        BB.items.add(item);
                        player.sendMessage(ChatColor.GREEN + "Items loaded: " + BB.items);
                    }
                }
            }
        }
    }
    
    and this is for creating the signs:
    Code:
    package icewhisker.bb;
    
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.SignChangeEvent;
    
    public class SignCreate implements Listener {
        
        BB plugin;
        
        SignCreate(BB main) {
            this.plugin = main;
          } 
        
        @EventHandler
          public void onSignChange(SignChangeEvent e) {
            Player player = e.getPlayer();
            if (player.isOp()) {
            // ----------------------------------------------------- <-- Storage
                if (e.getLine(0).equalsIgnoreCase("[bbstorage]")) {
                    e.setLine(0, ChatColor.GOLD + "[Stored]");
                    try {
                        Material.valueOf(e.getLine(1));
                    }
                    catch (Exception ex) {
                        e.getBlock().breakNaturally();
                        player.sendMessage(ChatColor.RED + "Line 2 must be a valid material");
                        return;
                    }
                    player.sendMessage(ChatColor.GREEN + "Created BlockBank Storage!");     
                }
                
            // ----------------------------------------------------- <-- Donate
               else if (e.getLine(0).equalsIgnoreCase("[bbdonate]")) {
                       e.setLine(0, ChatColor.GOLD + "[Donate]");
                       try {
                           Material.valueOf(e.getLine(1));
                       }
                   catch (Exception ex) {
                          e.getBlock().breakNaturally();
                          player.sendMessage(ChatColor.RED + "Line 2 must be a valid material");
                          return;
                   }
                   player.sendMessage(ChatColor.GREEN + "Created BlockBank Donation!");     
               }
            // ----------------------------------------------------- <-- Save
               else if (e.getLine(0).equalsIgnoreCase("[bbsave]")) {
                 e.setLine(0, ChatColor.GOLD + "[Save]");
               }
            // ----------------------------------------------------- <-- Load
               else if (e.getLine(0).equalsIgnoreCase("[bbload]")) {
                 e.setLine(0, ChatColor.GOLD + "[Load]");
                 try {
                    Material.valueOf(e.getLine(1));
                }
                catch (Exception ex) {
                    e.getBlock().breakNaturally();
                    player.sendMessage(ChatColor.RED + "Line 2 must be a valid material");
                    return;
                }
               }
            }
        }
    
    }
    
    
    I havent gotten round to even sending the materials in.
     
  5. Offline

    Not2EXceL

    icewhisker
    so you want to load the materials from the config onEnable?

    Should just be able to add this (something like this, not this exactly):
    Code:java
    1. FileConfiguration cfg = getConfig();
    2. List<String> list = cfg.getList("BlockBank.materialsLoaded");
     
  6. Offline

    icewhisker

    Not2EXceL
    Yeah I have tried that but when it reloads, onEnable and onDisable aren't registered, I am know trying to use hashmaps but I still don't know how to add and take away the hashmap from the config.yml. Even if the onEnable and onDisable worked on reload I still wouldn't be able to access the List list because you 'can't use static for the none static method getConfig()' and I wouldn't be able to find it in other classes.
     
  7. Offline

    Not2EXceL

    pass the instance to other classes. or make a singleton, and you can remove the static modifier from the arraylist

    and read through this:http://wiki.bukkit.org/Configuration_API_Reference

    im not sure if you understand what savedefaultconfig and what save config do.
     
  8. Offline

    icewhisker

    Not2EXceL
    ok I has a look at it, I know how to save hashmaps to a configfile, that all works but I don't know how to get it back again to use in other classes, this is my new main file:
    Code:
    package icewhisker.bb;
     
    import java.util.HashMap;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.java.JavaPlugin;
     
    public class BB extends JavaPlugin{
     
        static int number = 1;
     
        @Override
        public void onEnable() {
            Bukkit.getServer().getPluginManager().registerEvents(new SignCreate(this), this);
            Bukkit.getServer().getPluginManager().registerEvents(new Collection(this), this);
            Bukkit.getServer().getPluginManager().registerEvents(new Sending(this), this);
            this.getConfig().createSection("BlockBank.Loaded", itemshash);
            this.getConfig().getConfigurationSection("BlockBank.Loaded").getValues(true);
            }
     
        public static HashMap<String, Integer> itemshash = new HashMap<String, Integer>();
     
        @Override
        public void onDisable() {
            this.getConfig().set("BlockBank.Loaded", itemshash);
            this.saveConfig();
        }
     
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        Player player = (Player)sender;
     
            if (cmd.getName().equalsIgnoreCase("collection")) {
                if (player.getName().equalsIgnoreCase("icewhisker")) {
                    if (args.length == 0) {
                        player.sendMessage(ChatColor.RED + "Please specify a number");
                    }
                   
                    else if (args.length == 1) {
                        number = Integer.parseInt(args[0]);
                       
                        if (number > 0)
                            player.sendMessage(ChatColor.BLUE + "Collection rate: " + number);
                       
                        else if (number > 64) {
                            player.sendMessage(ChatColor.RED + "Please use a number less then 65");
                       
                        }
                       
                        else if (number <= 0) {
                            player.sendMessage(ChatColor.RED + "Please use a number higher then 0");
                        }
                    }
                }
            }
            return true;
        }
    }
     
     
     
    
     
  9. Offline

    Not2EXceL

    icewhisker you're not setting the hashmap to the config properly
     
  10. Offline

    icewhisker

    Not2EXceL
    sorry that I'm being a bother and that you probably think I'm terrible at java/bukkit (kind of accurate).
    So anyway how would you set the hashmap to the config, it seems to be working and it saves accurately.
    Also I don't know how to add to a hashmap this is my code:
    Code:
                else if (s.getLine(0).equalsIgnoreCase(ChatColor.GOLD + "[Donate]")) {
                    String item = String.valueOf(s.getLine(1).toString());
                    int itemamount = BB.itemshash.get(item);
                    BB.itemshash.put(item, itemamount + 10);
                    player.sendMessage(ChatColor.GREEN + "Donated " + amount + " " + item + " and extended the stored amount to " + BB.itemshash.get(item));
                }
    
    and it's producing the well known error: NullPointerException on this line:
    Code:
    int itemamount = BB.itemshash.get(item);
    
    I previously has the following:
    Code:
    else if (s.getLine(0).equalsIgnoreCase(ChatColor.GOLD + "[Donate]")) {
                    String item = String.valueOf(s.getLine(1).toString());
                    BB.itemshash.put(item, + 10);
                    player.sendMessage(ChatColor.GREEN + "Donated " + amount + " " + item + " and extended the stored amount to " + BB.itemshash.get(item));
                }
    
    and it didn't work because, It sent me the message whenever I right clicked the Donate sign:
    Donated 10 GRAVEL and extended the stored amount to 10.
    Each time so It wasn't actually adding 10 but setting the value to 10 (I think this is because java might understand + 10 in hashmap to mean positive 10?)
    So if you could help with that as well it would be great, sorry for rambling on a bit.
     
  11. Offline

    Not2EXceL

    icewhisker pm me for skype and I can help out more there.
    int itemamount = BB.itemshash.get(item);
    That line will throw a NPE, if your hashmap doesnt contain the string item. Add a check if that line returns null, then set itemamount to 0.
     
  12. Offline

    icewhisker

    Not2EXceL
    I prefer not using skype if it means talking.
    wow thanks it worked, the integer is rising as its supposed to, its now mainly the grabbing from the config file
     
  13. Offline

    M0n0clink

    icewhisker

    Code:java
    1. for(int i : hashmap.keySet()) {
    2. List<String> list = new ArrayList<String>();
    3. for(int j : hashmap.get(i) {
    4. String k = hashmap.get(i).get(j);
    5. list.add(k);
    6. }
    7. getConfig().set("data."i+"/"+j, k);
    8. }
    9. saveConfig();
    10.  
    11. //load list
    12. hashmap = new HashMap<Integer, HashMap<Integer, String>();
    13. if(getConfig().getConfigurationSection("data") != null) {
    14. Set<String> set = getConfig().getConfigurationSection("data").getKeys(false);
    15. for(String i : set) {
    16. String[] j = i.split("/", 1);
    17. int a = Integer.valueOf(j[0]);
    18. int b = Integer.valueOf(j[1]);
    19. HashMap<Integer, String> c = new HashMap<Integer, String>();
    20. List<String> list = getConfig().getStringList(i);
    21. for(String d : list)
    22. c.put(b, d);
    23.  
    24. hashmap.put(a, c);
    25. }
    26. }


    Extracted From: https://forums.bukkit.org/threads/saving-hashmap-to-file.129225/
     
  14. Offline

    icewhisker

    M0n0clink
    yeah thanks, but does that actually change the static hashmap to what is on the config file?
    say I need to use that on another class, how would I get what is on the config file?
    so using the code that was further down:
    Code:
        public void loadCredits() {
            itemshash = new HashMap<String, Integer>();
            if(getConfig().getConfigurationSection("credits") != null ) {
                Set<String> set = getConfig().getConfigurationSection("credits").getKeys(false);
            for(String credit : set) {
                int value = getConfig().getInt(credit);
                itemshash.put(credit, value);
                }
            }
            }
    
    then getting the value for the key on another class as normal would find what was on the config file right?

    M0n0clink
    ok from your post how would I use that on my <String, Integer> Hashmap?

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

    icewhisker

Thread Status:
Not open for further replies.

Share This Page