ArrayLists inside of a HashMap.

Discussion in 'Plugin Development' started by Irantwomiles, Aug 11, 2015.

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

    Irantwomiles

    I've been trying to add a team's feature into my plugin and yes I know there's hundreds of plugins out there that do this but I want to learn it. I did a little looking around StackOverFlow.com and Bukkit's old posts and I kept coming up with this line of code
    Code:
    HashMap<String, ArrayList<String>> team = new HashMap<String, ArrayList<String>>();
    
    Now I've only recently started to mess around with HashMaps and Maps in general but I can't seem to understand how I can add players to the teams. I assumed that the string would be the team name and the ArrayList for the players but how would I got about adding players to the ArrayList? This is what I ended up adding.
    Code:
     
    ArrayList<String> players = new ArrayList<String>();
    
    This is my /teamcreate command.
    Code:
            if(cmd.getName().equalsIgnoreCase("teamcreate")) {
                team.put(player.getName(), players);
                players.add(player.getName());
                sender.sendMessage("You created a team!");
            }
    
    Now I hope this has made sense and once again I'll repeat the question, How do I add the player to a team that has been created by someone else? For example I do /teamcreate and based on my code it should set the string to player.getName() but how do I add people to that list.
     
  2. Offline

    mythbusterma

    @Irantwomiles

    As a general rule, you should not nest Collections inside of other Collections. It is usually an indication that you need to create an Object for it, in this case a "Team" class or something that nature seems appropritate, this would change the definition to:

    HashMap<String, Team>

    Which is probably a lot closer to what you need, but there really isn't any need for it to be a Map anymore, so:

    HashSet<Team>

    Would probably be your best bet here. You can then iterate through the Set to find a Team by its name (although if you're going to be doing this frequently, you may just want to stick with a Map).

    As far as your original question, you're going to need a Collection that exists at the class scope (i.e. is a member of either your main class or the command executor).
     
  3. Offline

    Irantwomiles

    @mythbusterma As of right now I have everything in my main class just to test things out and see how they go. But I'm trying to allow a way to create unlimited teams, If I'm going in the wrong direction please guide me else where.
     
  4. Offline

    mythbusterma

    @Irantwomiles

    Well then make it a member of your "main class."
     
  5. Offline

    Irantwomiles

    Ok let me change my question. How would I go about making a teams plugin, I don't want a set amount of teams I already know how I could make something like that. I want something temporary for a practice server, no need for configs or team passwords just a stimple teams plugin.

    EDIT: I'm sure its nothing too crazy complicated and I'm overthinking this way to much but Honestly any help would make me a little bit more sane.
     
  6. Offline

    mythbusterma

  7. Offline

    Irantwomiles

    Ok, Never used HashSets before, gonna take a loot at that. I'm sure I'll have more questions :p

    I think I'm more confused than ever. @Mythbuster
     
    Last edited by a moderator: Aug 11, 2015
  8. Offline

    teej107

    First create a separate class named something like Team.
     
  9. Offline

    Irantwomiles

    I did.
     
  10. Offline

    teej107

    Now what has you confused?
     
  11. Offline

    Irantwomiles

    I'm confused on how I can allow one player to create the team and invite others with this line of code. If this is the correct line of code I should be using. There's just something about it that when I look at this, it makes my mind just go blank.
    Code:
    HashMap<String, ArrayList<String>> team = new HashMap<String, ArrayList<String>>();
    
    EDIT: I dont think is a correct way of doing what I want and I can't seem to come up with something on my own. IF this is the correct way can I get a push or shove in the right direct.
     
  12. Offline

    teej107

    @Irantwomiles Forget your HashMap for now and let's focus on the Team class. The Team class is supposed to replace the ArrayList in your Map. In your Team class, create methods to add/remove players to the team. You can even put a Collection in the Team class to hold the Players that are part of the team. Alternatively you may also have the Team class extend the Collection instead.
     
  13. Offline

    Irantwomiles

    For example, If I were to do the command /team create <Name> It actually creates the team and the team name but Do I add the team name to an arrayList of its own? or do I do HashMap.Put(args[1], player.getName());
    @teej107
     
  14. Offline

    teej107

    @Irantwomiles The key part of the Map will be for the name so you can get a reference of the team by name. The values of the Map will be the team.
     
  15. Offline

    Irantwomiles

    @teej107 So I assume you need a List of some sort in my Teams class, so how would I be able to tell who is in what team?
     
  16. Offline

    teej107

    1. You don't need a List unless you need the #get() method. Otherwise it'll be better to use a (Hash)Set instead.
    2. You can create your own method to tell who is in the team
    3. You can create your own method to get the team players
    4. You can also just extend <insert needed Collection here> for your Team class. Doing this will mean you don't need to do 2 or 3
     
  17. Offline

    Irantwomiles

    Thank you, I will post my Team class soon.

    Code:
     
    package me.iran.bukkit;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    
    import org.bukkit.entity.Player;
    
    public class Team extends Main{
       
        private static List<String> allTeams = new ArrayList<String>();
                            //Team Name | Players
        private static HashMap<String, String> playerTeams = new HashMap<String, String>();
       
        //private static String teamName;
       
        public static void createTeam(Player tName, Player player) {
            playerTeams.put(player.getName(), player.getName());
            allTeams.add(player.getName());
        }
       
        public static String getName(String teamName) {
            return teamName;
        }
       
        public static void add(Player player) {
            playerTeams.put(player.getName(), player.getName());
        }
       
        public static void invite(Player player) {
            if(!hasTeam(player)) {
                playerTeams.put(player.getName(), player.getName());
            }
        }
       
        public static void accept(Player player) {
            if(playerTeams.containsValue(player.getName())) {
               
            }
        }
       
        public static boolean remove(Player player) {
            if(hasTeam(player)) {
                return false;
               
            } else {
                playerTeams.remove(player.getName());
                return true;
            }
        }
       
        public static boolean hasTeam(Player player) {
            return playerTeams.containsKey(player.getName());
        }
       
        public static String getTeam(Player player) {
            if(!hasTeam(player)) {
                return null;
            } else {
                return playerTeams.get(player.getName());
            }
        }
    }
    
    
    So this is my team class. Did I do it correctly? or in the right direction? @teej107

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

    teej107

    @Irantwomiles I only saw the first few lines and I am going to say no, you didn't do it correctly.

    1. Don't extend Main because you should only have one JavaPlugin class.
    2. Get rid of the static and think of each Team object as its own team.
    I do gotta say that you are close in the right direction. Just to put this out there that writing Bukkit plugins requires you to have a comfortable knowledge of Java.
     
    Garnetty likes this.
  19. Offline

    javipepe

    I think the best think you could do here is creating a constructor class for the Team. Meaning to create a class called "Team" then creating a public Team and then making it build it, you could do something like this.

    Code:
    public class Team{
    
      ChatColor color;
      String name;
      int maxoverfill;
      List<Player> players;
    
      public Team(ChatColor color, String name, int maxoverfill){
        this.color = color;
        this.name = name;
        this.maxoverfill = maxoverfill;
        players = new ArrayLIst<Player>();
    
      }
    
      public ChatColor getColor(){return color;}
      public String getName(){return name;}
      public int getMaxOverfill(){return maxoverfill;}
      public List<Player> getPlayers(){return players;}
    
    }
    Then you could create a class maybe called "TeamUtils" where the methods for the team that are not given on the very start and are not final (adding/removing players, list of all teams, etc), something like:
    Code:
    public static List<Team> teams = new ArrayList<Team>();
    
        public static void createTeam(ChatColor c, String name, int maxcapacity){
            Team t = new Team(c, name, maxcapacity);
            teams.add(t);
        }
        public static void deleteTeam(Team t){
            teams.remove(t);
        }
    
        public static Team getTeamByName(String s){
          
                Team target = null;
    
                for(Team t : teams){
                    if(t.getName().equalsIgnoreCase(s)){
                        target = t;
                    }
                }
    
                return target;
            }
        }
        public static Team getTeamOfAPlayer(Player p){
    
            for(Team t: teams){
                if(t.getPlayers().contains(p)){
                    return t;
                }
            }
            return null;
        }
    
        public static void addPlayerToTeam(Player p, Team t){
            t.getPlayers().add(p);
        }
    
        public static void removePlayerFromTeam(Player p, Team t){
            t.getPlayers().remove(p);
        }
    
        public static List<Team> getAllTeams(){
            return teams;
        }
    Maybe that can help you, I think it's a better idea. Also you could make the player adding and removing inside of the constructor, but I just decided to make it within an external method.

    Look at my post above, it will sure help you :)

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

    Ricecutter0

    Today I found a method of doing this.

    Code:java
    1. private Map<String, List<String>> teams = new HashMap<String, List<String>>();


    Then you have your command that creates a team:

    Code:java
    1. if(cmd.getName().equalsIgnoreCase("teamcreate")){
    2. if(args.length < 1){
    3. sender.sendMessage("/teamcreate [team-name]");
    4. return true;
    5. }
    6. teams.put(args[0], new ArrayList<String>());
    7. }


    Then adding players to the team:

    Code:java
    1. if(cmd.getName().equalsIgnoreCase("addplayer")){
    2. if(args.length < 2){
    3. sender.sendMessage("/addplayer [team] [player]");
    4. return true;
    5. }
    6. if(!data.containsKey(args[0])) return true;
    7. data.get(args[0]).add(args[1]);
    8. }


    This is just if you want to save it to a file.

    Saving:
    Code:java
    1. private final static String CONFIG_NAME = "teams.yml";
    2.  
    3. public void save(Map<String, List<String>> teams){
    4.  
    5. File datafolder = plugin.getDataFolder();
    6.  
    7. //check if the data folder exists.
    8.  
    9. File f = new File(datafolder, CONFIG_NAME);
    10. //check if "f" exists.
    11.  
    12. YamlConfiguration conf = new YamlConfiguration();
    13. conf.options().pathSeparator('.');
    14.  
    15. try {
    16. conf.load(f);
    17. } catch (Exception e) {
    18. e.printStackTrace();
    19. return;
    20. }
    21.  
    22. for (String key : teams.keySet().toArray(new String[data.size()]))
    23. conf.set(key, teams.get(key));
    24.  
    25. try {
    26. conf.save(f);
    27. } catch (IOException e) {
    28. e.printStackTrace();
    29. }
    30. }


    Loading:

    Code:java
    1. public Map<String, List<String>> loadTeams(){
    2.  
    3. File datafolder = plugin.getDataFolder();
    4.  
    5. //check if the data folder exists.
    6.  
    7. File f = new File(datafolder, CONFIG_NAME);
    8. //check if "f" exists.
    9.  
    10. YamlConfiguration conf = new YamlConfiguration();
    11. conf.options().pathSeparator('.');
    12. try {
    13. conf.load(f);
    14. } catch (Exception e) {
    15. e.printStackTrace();
    16. return null;
    17. }
    18.  
    19.  
    20. Map<String, List<String>> teams = new HashMap<String, List<String>>();
    21.  
    22. for(String key : conf.getKeys(false).toArray(new String[0])){
    23. if(conf.isList(key))
    24. teams.put(key, conf.getStringList(key));
    25. }
    26.  
    27. try {
    28. conf.save(f);
    29. } catch (IOException e) {
    30. e.printStackTrace();
    31. }
    32.  
    33. return teams;
    34. }


    Then in your main class load/save it. (Make sure to save after editing the hashmap!)
    Code:java
    1. Storage s = new Storage(this);
    2. //Replace storage with your class name with the saving and loading methods
    3.  
    4. private Map<String, List<String>> teams = new HashMap<String, List<String>>();
    5.  
    6. @Override
    7. public void onEnable() {
    8. data = s.loadTeams();
    9. }
    10.  
    11. @Override
    12. public void onDisable() {
    13. s.save(teams);
    14. }
     
  21. Offline

    mythbusterma


    I hope you realise this would not work at all. Look up what the static modifier actually does.


    @Ricecutter0

    See my first post for why you shouldn't do this.
     
  22. Offline

    javipepe

    Oops messed up :p, fixed
     
  23. Offline

    Irantwomiles

    Thanks @javipepe @mythbusterma @teej107 @Ricecutter0 . I'm gonna take what you gave me and post updated code, Hopefully I'll be closer! thanks guys.

    @javipepe so I'm following your Team Class you did and I'm having trouble with this part.
    Code:
            if(cmd.getName().equalsIgnoreCase("teamcreate")) {
                String name = args[0];
                int maxcap = 5;
                Team.createTeam(ChatColor.GREEN, name, maxcap);
                return true;
            }
          
            if(cmd.getName().equalsIgnoreCase("teaminvite")) {
                Player target = Bukkit.getServer().getPlayer(args[0]);
                Team.addPlayerToTeam(target, Team.getTeamByName(s));
            }
    
    How do I get the Team Name in teaminvite when its not a global variable? Do I have to make String name; an Global variable?

    EDIT: My Plugin wont show up on my test server and I'm 100% sure its because I didnt add anything to my main class that can shows that I have the Team class. What am I suppose to do?

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

    Konato_K

    @Irantwomiles
    Code:
    class Pie {
      private Flavour flavour = Flavour.PIE;
    
      public Flavout getFlavour() {
        return flavour;
      }
    }
     
  25. Offline

    Irantwomiles

    @Konato_K this is what I currently have.
    Code:
        private Main plugin;
       
        public Team(Main plugin) {
            this.plugin = plugin;
        }
     
     
  26. Offline

    mythbusterma

  27. Offline

    Irantwomiles

    My plugin won't load.
     
  28. Offline

    teej107

  29. Offline

    Irantwomiles

    EDIT: Fixed the loading problem. But still have a couple questions regarding team name and inviting players to team.

    As of right now my problems all lead to getting the Team Name and adding players to the team. This is what I have to create a team.
    Code:
            Player player = (Player) sender;
            name = args[0];
            if(cmd.getName().equalsIgnoreCase("teamcreate")) {
                int maxcap = 5;
                Team.createTeam(ChatColor.GREEN, name, maxcap);
                Team.teams.add(Team.getTeamByName(name));
                player.sendMessage("Team " + name + " Created!");
              
            }
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 11, 2016
  30. Offline

    teej107

    @Irantwomiles if you continued to follow what I was showing you, those problems wouldn't be a problem.
     
Thread Status:
Not open for further replies.

Share This Page