[TUT] Setting up Teams for your Plugin!

Discussion in 'Resources' started by MoeMix, Aug 4, 2014.

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

    MoeMix

    Hey! First tutorial for me and I just wanted to share a nice little resource. There are many methods of creating teams and I wanted to share this resource that is very reliable since it has it's own methods and is pretty efficient.

    This is how to setup teams for your minigame or whatever you're trying to code! You should have some knowledge regarding Java's object oriented approach to classes, static methods and such. With that all aside, let's start!

    To begin, let's create a Team class which will store all of the information for our teams. All the code and the methods will be explained in the comments within the code :)
    Code:java
    1. package Teams;
    2.  
    3. import java.util.ArrayList;
    4. import java.util.HashMap;
    5.  
    6. import org.bukkit.entity.Player;
    7.  
    8. public class Team {
    9. // a list of all the teams that we create. Ex: a red team, blue team, etc. will all be stored in this list!
    10. public static ArrayList<Team> teams = new ArrayList<Team>();
    11. // This is the hashmap we use to put the player in a team. Notice, it takes in a String (player name) and a Team.
    12. public static HashMap<String, Team> playerTeams = new HashMap<String, Team>();
    13. // this is going to be a string that represents the team color. So for the red team, this variable would be "Red".
    14. public String teamColor;
    15.  
    16. // our constructor which takes in a string. This string will be the team color.
    17. public Team(String teamcolor){
    18. // setting the 'teamColor' variable equal to the 'teamcolor' variable so we could use 'teamColor' throughout this class.
    19. teamColor = teamcolor;
    20. // adding the team that we just created to the array list that we previously created called 'teams'.
    21. teams.add(this);
    22. }
    23. // Method to add the player to a team.
    24. // Notice this takes in both a Player; p, and a Team; team.
    25. public static void addPlayer(Team team, Player p){
    26. // putting the players name in the hashmap that holds all the player teams
    27. playerTeams.put(p.getName(), team);
    28. }
    29. // Removing the player
    30. public static void removePlayer(Player p){
    31. // checking if the player is in a team first. then removing the player from the hashmap.
    32. // Look for the hasTeam method below :)
    33. if(hasTeam(p) == true){
    34. playerTeams.remove(p.getName());
    35. }
    36. }
    37. // check if player has a team
    38. public boolean hasTeam(Player p){
    39. // checking if the player is in the 'playerTeams' hashmap...if true then that player is in a
    40. return playerTeams.containsKey(p.getName());
    41. }
    42. // this method returns the team of the player.
    43. public static Team getTeam(Player p){
    44. // if the player has a team....
    45. if(hasTeam(p) == true){
    46. // then return the Team he/she is in from the playerTeams hashmap!
    47. return playerTeams.get(p);
    48. }
    49. // if not...
    50. else if(hasTeam(p) == false){
    51. // return null!
    52. return null;
    53. }
    54. return null;
    55. }
    56. // This method returns a string. It will either return "Red" "Blue" or whatever you pass into the constructor.
    57. public String getTeamColor(){
    58. return teamColor;
    59. }
    60.  
    61. }
    62.  


    Now that's pretty much all that is needed for creating and managing the teams. Let's put this into action!

    First... create the teams that you want.
    Code:java
    1. public class TeamsTest extends JavaPlugin{
    2. Team redTeam = new Team("Red");
    3. Team blueTeam = new Team("Blue");
    4. }

    Java's Object Oriented Programming is pretty neat huh? We have instantiated the Teams class twice but they are not the same instance since we called in "new Team(someString)" twice. So now we have two instances of the Team class.

    I coded this library using static methods so to access them you don't need an instance of the Team class but to add players to teams and such, you will need to. However, there are methods that need to be static like getTeam and hasTeam. To access them just use Team.WHATEVERMETHODHERE();

    Now we can use the methods like addPlayer, getTeam, etc. We can do Team.addPlayer(redTeam, player) and much more! Here is a code example on how to add a player to the red team and remove a player using the /joinred and /leavered commands respectively.
    Code:java
    1. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
    2. Player p = (Player)sender;
    3. if(label.equalsIgnoreCase("joinred")){
    4. Team.addPlayer(redTeam, p);
    5. p.sendMessage("You just joined the RED team!");
    6. }
    7. if(label.equalsIgnoreCase("leavered")){
    8. if(Team.hasTeam(p)){
    9. Team.removePlayer(p);
    10. p.sendMessage("You just left the RED team!");
    11. }
    12. }
    13. return true;
    14. }


    Now, as I was writing this tutorial, I just thought of a simpler method. I don't feel like erasing everything I just did so I'll just tell you if you think you are able to make this code more efficient. You can make it so that you can do redTeam.addPlayer(p) instead of Team.addPlayer(redTeam, p). In the Team class just change the method to this:
    Code:java
    1. public void addPlayer(Player p){
    2. // putting the players name in the hashmap that holds all the player teams
    3. playerTeams.put(p.getName(), this);
    4. }

    and now to add the player:
    Code:java
    1. if(label.equalsIgnoreCase("joinred")){
    2. redTeam.addPlayer(p);
    3. p.sendMessage("Joined RED team");
    4. }


    That's pretty much it for this tutorial. You can go ahead and mess around with the rest of the methods and I hope this works out for you and helps you at least a little bit :p Like I said, this is my first tutorial and I know there is a lot of criticism that will come my way regarding this but I hope that they are all constructive and helpful. They most likely will be this is the Bukkit community always trying to help out <3 Anyway, thanks for reading and leave a like if it actually was helpful!

    P.S: Yes, most of these methods are static. But why not? I try to use static methods as frequently as I can just in case an instance isn't needed. If you're going to shout at me about this then I'm sorry, because I couldn't care less :)
     
  2. Offline

    Phasesaber

    For the Team#hasTeam(Player p); , you can make it just one line.
    Code:
    public void hasTeam(Player p){
    return playerTeams.containsKey(p.getName());
    }
    
    containsKey() return a boolean, so just return that boolean for the method instead of having an if statement.
     
    MoeMix likes this.
  3. Offline

    MoeMix

    Thanks! I'll change the code now!

    Phasesaber
    Just a little notif, that method has to be public void boolean hasTeam(Player p){} It returns a boolean so you have to set it up like that

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

    FabeGabeMC

    MoeMix
    And you don't have to do == true on those statements ;)
     
    Phasesaber likes this.
  5. Offline

    Phasesaber

    MoeMix no, you shouldn't have the void, just the public boolean.
     
  6. Offline

    raGan.

    MoeMix
    Since you are using Map, you can rely on it returning null if it doesn't contain mapping for a key.
    Code:
    public static Team getTeam(Player p){
        return playerTeams.get(p);
    }
    Edit: Same applies to remove method. You don't need to do any check there as well.
     
    Phasesaber likes this.
  7. Offline

    Phasesaber

    raGan. I was just going to put this :p
     
  8. Offline

    Panjab

    So where is the big benefit using this instead of the implemented Scoreboard methods?
     
  9. Offline

    AoH_Ruthless

    MoeMix
    1. As Panjab mentioned, why should I use this over Bukkit API?
    2. Because you are instantiating the class (calling multiple Team instances at any given point), it is extremely unwise to use static modifiers. This also applies to the use of public fields. Instead, you should have private/protected fields with the use of getters, if necessary at all to avoid bad accessing. You tell us not to mention it because you can't care less ... that is extremely arrogant. "Look at this code, it's amazing! PS dont comment on static because i dont care about ur suggestions k bye"
    3. An aesthetic pointer: Comments everywhere extremely reduce the readability of your code, despite what you may think. One common thing a lot of people do is point out the obvious. Anyone reading your code can figure out certain stuff for themselves, so overzealous use of comments is bad. Yes, there is a such thing as too much commenting. Read more here: http://davidwalsh.name/code-commenting (while I am unfamiliar with the author's credibility, I agree with several points in this blog-esque article).
    4. The mixed-use of static with constructor, and your odd editing style makes me confused as to how the whole code works. Also, you are instantiating redTeam and blueTeam outside of the onEnable or any constructor in your main class ... won't work.
    5. Did you even proof read your code? ...
     
  10. Offline

    MoeMix

    Phasesaber Panjab raGan. FabeGabeMC
    Thanks for the constructive criticism. Helps out a lot :)

    AoH_Ruthless
    As I stated in the op, there is nothing wrong with using these static methods. I made them static anyway, its not like it will inflict on how the code works. Because...IT STILL DOES. Also, if you are so picky about me using static methods then just follow the little addon I put that explains how to NOT use the static methods. I just didn't feel like erasing everything I have already written.

    Also, I apologize if I don't follow some conventions but, hey, if it works then it works. The output is not about how pretty the code looks, but how it works. And if someone actually wanted to use this resource then they would read all the comments no matter how it looked. This was meant for those who wanted to use this resource so if you aren't interested then why bother telling me what to do.

    As for the small Team#hasTeam mistake, thanks for catching that I added it hastily on my way to dinner. Nonetheless, it is now fixed.

    Thanks again to all!
     
    Phasesaber likes this.
  11. Offline

    Phasesaber

    Great :D
     
    MoeMix likes this.
  12. Offline

    bobacadodl

    Might be nitpicking, but this statement is incorrect
    Even if you passed the same exact string into the constructor twice, you would still get 2 separate instances of the Team class
     
  13. Offline

    MoeMix

    Eh, I guess I could have worded that a bit differently. I know that no matter what's passed into the constructor as long as you use that 'new' component in java it will instantiate a new class and since the variables are different. I can go ahead and fix that up since I can see how someone could be misled by how I worded that quite terribly lol. Thanks for catching that!
     
  14. Offline

    xTrollxDudex

    MoeMix
    Again swatting away constructive criticism.

    Since you are having people use this as developers, the outward AND inward appearance of the code makes sense - messy code is hard to understand and follow, and it would do a great amount of people a favor by being able to easily see what is going on.

    Using static as much as you can? Yeah...

    Stop. No really, stop. Earlier in the post you mentioned the "magic" of OOP, and now you have static methods? Better, if you have a singular class, turn it into an interface and the subclass will be an inner implementation of the interface.
     
  15. Offline

    MoeMix

    I am grateful to all the constructive criticism however, I am prioritizing the ones that actually effect how the code works. Why does everyone get these emotions for just using static methods? lol, seriously, you guys need to calm down it doesn't change anything. There are some methods that need to be static and so I just went ahead and made all of them static so that I wouldn't have to worry about what should or shouldn't be static. And as long as you call it in correctly (with an instance or not) then congratulations! the code works! Plus, if your IDE even lets you create the method and don't get any errors upon creating it then woop de doo, you can use it.

    And again, if you feel like you DON'T want to use the static methods read the part where I explain how. I wrote that sections specifically for those that lean more towards how the code works than just getting it to work.
     
  16. Offline

    minepress

    Hey Moe,

    So I've been slowly learning Java. I decided to use your tutorial as a testing platform.

    Code:java
    1. @Override
    2. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    3. Player p = (Player)sender;
    4. int monstercount = 0;
    5.  
    6. if(label.equalsIgnoreCase("joinhuman")){
    7. humanTeam.addPlayer(p);
    8. p.sendMessage("You are a HUMAN");
    9. }
    10. if(label.equalsIgnoreCase("joinmonster")){
    11. if(monstercount < 1) {
    12. p.sendMessage("There is already a monster, moving to human team");
    13. monsterTeam.addPlayer(p);
    14. } else if (monstercount > 2){
    15. monsterTeam.addPlayer(p);
    16. p.sendMessage("DESTROY THEM");
    17. }
    18. }
    19. return true;
    20. }


    Was just wondering if you could suggest a better method behind what I'm doing etc?

    Thanks :)
     
  17. Offline

    MoeMix

    minepress
    Hey dude, thanks for using the tut! As for your question, I'm not exactly sure what the monstercount integer is nor how you're changing it because in your code it shows that you set it equal to 0. So therefore, it wouldn't be greater than 2. Try explaining exactly what you're doing so I can better assist ya
     
  18. Offline

    minepress


    Hey Moe,

    It's basically querying how many people are on the monster team.

    So it starts of as 0 and resets to 0 when called. When someone goes into monsterTeam it increases the value of monstercount to 1. Then when someone else tries to join, it queries whether or not they can be in that team or not.
     
  19. Offline

    raGan.

    minepress
    I think monsterTeam.size() would be more convenient.
     
  20. Offline

    minepress


    I don't suppose you'd mind explaining why? :)
     
  21. Offline

    raGan.

    Not only it is easier to identify what the code is doing, (@MoeMix wasn't able to tell at first) but also this information is already kept by a collection used to store players in a team, so you don't need to manually keep track. Unless of course you are not keeping players (their names) stored in team object and do everything in a static way, which is less object oriented approach.
     
    minepress likes this.
  22. Offline

    MrDplugins

    raGan. minepress I don't understand how you got the teams to only allow a certain amount of players. Could you explain or send me a code snippet?
     
  23. Offline

    minepress


    One method could be using an if statement? if the teams size is greater than a specific amount then don't join team
     
  24. Offline

    Dragonphase

    MoeMix

    I'm going to comment on your use of statics, and I know a lot of people already have but, it riddles my jimmies. You should not be using statics everywhere you can for one simple reason - it makes the method (or field) belong to the class and not any one instance of the class. It is clear that your Team class is not a singleton therefore it should not contain static methods and fields that depend on instances of a Team object.

    The only situation you should be using statics is for a plugin instance (for an API for example) or within a Utility class, where the static fields are final (thus making them constant) and the static methods do not depend on any instance of an object to return a value.

    A really simple solution to this problem is to create a TeamManager class which stores your collection of Team objects. From here, you can add teams, remove teams, and do everything that you did originally, but in a non-static context. You would create one non-static instance of TeamManager within your plugin's main class with a public getter method, allowing you to use plugin.getTeamManager();
     
  25. Offline

    MrDplugins

    minepress Yes but how do I add that and call the method for the teams?
     
  26. Offline

    minepress

    Have you actually attempted to write this? What I've said is basic 101 in most programming
     
  27. Offline

    MrDplugins

    minepress I have I always end up with having to create the method but I don't understand how to add it into the Team class :p (sorry I'm a noob)
     
  28. Offline

    minepress

    I suggest you go read some Java tutorials... http://www.learnjavaonline.org/
     
  29. Offline

    MoeMix

    If you want to directly add it in the Teams class you can modify the addPlayer method in the Teams class. check if the size of the team is less than a certain number, then do playerTeams.put(blahblah).

    Dragonphase
    Yes, thank you for your actual constructive criticism and as a secondary approach to this I added a small bit at the bottom that shows how to use the Teams class in a more object oriented approach. There are many workarounds and, yes, avoiding statics is a more conventionally accepted approach but why not show both ways. It's not hurting/affecting the overall result since the Teams classes are initiated on the start.
     
  30. Offline

    MrDplugins

    MoeMix How would you test to see if a team contained a player?
     
Thread Status:
Not open for further replies.

Share This Page