Add custom methods to Player

Discussion in 'Plugin Development' started by colozz, Jun 19, 2013.

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

    colozz

    Hi, I'm making a plugin where there is two teams.
    In the game, there is some actions only the red players can do, so I was searching to make custom methods like this :

    Code:java
    1. public class CustomPlayer {
    2.  
    3. private Player player;
    4.  
    5. public CustomPlayer(final Player player)
    6. {
    7. this.player = player;
    8. }
    9.  
    10. private String team;
    11.  
    12. public Player getPlayer()
    13. {
    14. return player;
    15. }
    16.  
    17. public void setTeam(String team)
    18. {
    19. this.team = team;
    20. }
    21.  
    22. public String getTeam()
    23. {
    24. return team;
    25. }
    26. }
    27.  


    I add the player in the red team when he interacts with a sign :

    Code:java
    1. CustomPlayer customPlayer = new CustomPlayer();
    2. customPlayer.setTeam("red");


    And there is no error but... when I have to ckeck if the player is in the good team I do :

    Code:java
    1. CustomPlayer customPlayer = new Customplayer(p);
    2.  
    3. if(customplayer.getTeam() == "red")
    4. {
    5. // Doing some stuff
    6. }


    And I'm getting a NullPointerException.

    Thank you for helping.
     
  2. Offline

    CoderCloud

    You team variable isnt set use this as your constructor:
    Code:
     public CustomPlayer(final Player player)
        {
            this.player = player;
            this.team = null;
        }
    And I would replace 'private Player player;' with 'private final Player player;'
     
  3. Offline

    colozz

    Ok, so I changed "private Player player" to "private final Player player" and add my team variable in the constructor.
    I add the player to a team when he hits a sign with :

    Code:java
    1. CustomPlayer customPlayer = new CustomPlayer();
    2. customPlayer.setTeam("red");


    And when he hurts the check sign i'm getting a NullPointerException :

    Code:java
    1. CustomPlayer customPlayer = new CustomPlayer(p);
    2. customPlayer.getPlayer().sendMessage(customPlayer.getTeam());
     
  4. Offline

    iKanak

    You are creating two separate instances of CustomPlayer and expecting them to be the same (and not passing a player to your first instance?). How you are going about this is a bit weird to me (although I don't know what your end goal is), but you need to store the CustomPlayer in an array/list and get this instance (when needed) rather than creating a new one.
     
  5. Offline

    colozz

    Ok, I'm gonna try.

    If I store my CustomPlayers in an ArrayList<CustomPlayer>, how can I get my Customlayer when I want to do customPlayer.getTeam() ?

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

    Chinwe

    Code:
    if(customplayer.getTeam() == "red")
    Shouldn't that be:
    Code:
    if(customplayer.getTeam().equals("red"))
    as you are comparing Strings?
     
  7. Offline

    colozz

    Like iKanak said, i'm using two differents instances.
     
  8. Offline

    lycano

    colozz please, never store the player object anywhere. You dont need the whole object you probably only need partial information and if you ever need to get the location then you could just add a method that can do that through bukkit API.

    Modifications to your class:

    private String playerName = "Player";

    // constructor
    public CustomPlayer(String playerName) {
    this.playerName = playerName;
    }

    public Player getPlayer() {
    return Bukkit.getPlayerExact(this.getName());
    }

    public String getName() {
    return this.playerName;
    }

    getPlayer("Player").getLocation();

    could also be linked to your class as

    public Location getLocation() {
    return this.getPlayer(this.getName()).getLocation();
    }

    Also checkout my post at http://forums.bukkit.org/threads/ghost-players-not-working.153297/#post-1714104 this might help you a bit if you ask yourself how you could actually add some custom properties to a generic object.
     
  9. Offline

    colozz

    Ok I try to modify my code this way.

    Ok so I've modified my code but I don't understand how to use my customPlayer.setTeam() and how to use my customPlayer.getTeam, I know I tried to use
    Code:java
    1. CustomPlayer customPlayer = new CustomPlayer(p.getName);
    but it's again another instance.

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

    lycano

    for getTeam i would create another class and create a hashmap to store the team assignment.

    Something like i posted in another post or easy way ...

    Map<String, TeamAssignment> teamAssignment = new HashMap<String, TeamAssignment>();

    TeamAssignment is abstract class that will be extended by TeamRed or TeamBlue or whatever.

    Make a method that can getTeam() for the custom player and access the teamAssignment hashmap.

    Of course you need to addTeam first ... something like teamAssignment.put("Player", new TeamRed());

    ..
     
  11. Offline

    colozz

    I didn't succeed because I never used hashmaps and I'm not very good in english so I'm gonna create two ArrayList<String> in the main class and add the players name inner.
    thank you for your help :/
     
  12. Offline

    lycano

    colozz Tell me exactly what you need and i might be able to give you a complete class package =)

    What data do you need from the Player in CustomPlayer object?
    Should the CustomPlayer object hold its data?
     
  13. Offline

    AmShaegar

    Did you ever think about mamkingn a Team class that contains a list of players? I think, this is the more straightforwarded way.
     
  14. Offline

    colozz

    Ok so, I'm creating a a game where there is two teams. They can join the game by typing /join. Here what I done works perfectly. But I searched to known in which team a player is when he enters a specific area. If he is red, he is teleported and if he is blue, nothing happends. So I created in the first version of my plugin two ArrayList<String> and when a player join a team (by typing /join) I did :
    Code:java
    1. teamBlue.add(p.getName());

    But when I have to check if the player is in the good team I did :
    Code:java
    1. if(teamRed.contains(p.getName()) {
    2. // teleportation
    3. }

    But the problems began, with the update of my plugin, each player have more properties and if later I have to make more teams, my code will be unreadable and non-extensible.

    So I just want to create a class where I make getters and setters for the players like setTeam() and getTeam().
    So in the code I will write :
    Code:java
    1. int r = (int) (Math.random * 10000);
    2. if(r <= 5000) {
    3. p.setTeam("Blue");
    4. }

    And :
    Code:java
    1. if(p.isBlue()) {
    2. // teleportation
    3. }


    Thank you for helping :)
     
  15. Offline

    AmShaegar

    Okay, so then I would suggest one of those two different Methods: Either use Metadata or a PlayerProperties object.

    There are good tutorials for Metadata. You can set Metadata for many things like players, locations, blocks etc. It is as easy like this:
    Code:java
    1. public static void setMetadata(Metadatable obj, String key, Object value) {
    2. obj.setMetadata(key,new FixedMetadataValue(CaptureTheFlag.getPlugin(), value));
    3. }
    4.  
    5. public static MetadataValue getMetadata(Metadatable obj, String key){
    6. for(MetadataValue value : obj.getMetadata(key)){
    7. if(value.getOwningPlugin().getDescription().getName().equals(CaptureTheFlag.getPlugin().getDescription().getName())){
    8. return value;
    9. }
    10. }
    11. return null;
    12. }


    Method two is a PlayerProperties object similar to what you did. Instead of creating a new one every time and save the Player inside the object do something like this:

    Code:java
    1. private HashMap<String, PlayerProperties> properties = new HashMap<String, PlayerProperties>;
    2.  
    3. public void create(Player player) {
    4. PlayerProperties p = new PlayerProperties();
    5. p.setTeam("red");
    6. properties.put(player.getName(), p);
    7. }
    8.  
    9. public void check(Player player) {
    10. PlayerProperties p = properties.get(player.getName());
    11. if(p.getTeam().equals("red")) {
    12.  
    13. }
    14. }
     
  16. Offline

    lycano

    colozz ok so we have:
    • PlayerData
    • TeamAssignment
    • Rules per Team
    I will try to create something for you to use.
     
  17. Offline

    colozz

    Ok, thank you, I'm gonna try to make something too :)
     
  18. Offline

    lycano

    AmShaegar afaik Metadata is not persistent. Has this changed?
     
  19. Offline

    Ivan

    No it hasn't.
     
  20. Offline

    colozz

    AmShaegar, where did you found the object PlayerProperties ?
     
  21. Offline

    lycano

    colozz here is something that should help you.

    I left out the Rule system as i think you can do that now on your own =)

    Code:java
    1.  
    2. public interface CustomPlayer {
    3.  
    4. public Player getPlayer();
    5. public String getName();
    6. public String getDisplayName();
    7. public Location getLocation();
    8.  
    9. }
    10.  


    Code:java
    1.  
    2. public class TeamPlayer implements CustomPlayer {
    3.  
    4. private String playerName;
    5. private Team membership;
    6.  
    7. public TeamPlayer(Player player) {
    8. this(player.getName(), new TeamNone());
    9. }
    10.  
    11. public TeamPlayer(Player player, Team membership) {
    12. this(player.getName(), membership);
    13. }
    14.  
    15. public TeamPlayer(String playerName) {
    16. this(playerName, new TeamNone());
    17. }
    18.  
    19. public TeamPlayer(String playerName, Team membership) {
    20. this.playerName = playerName;
    21. this.membership = membership;
    22. }
    23.  
    24. /**
    25.   Get the Player's name
    26.  
    27.   @return String The player's name
    28.   **/
    29. public String getName() {
    30. return this.playerName;
    31. }
    32.  
    33. /**
    34.   Get the Player's current Display-Name
    35.  
    36.   @return String The Player's currently assigned display name
    37.   **/
    38. public String getDisplayName() {
    39. return this.getPlayer().getDisplayName();
    40. }
    41.  
    42. /**
    43.   Checks the Player's online-status
    44.  
    45.   @return boolean true if online otherwise false
    46.   **/
    47. public boolean isOnline() {
    48. return Bukkit.getOfflinePlayer(this.getName()).isOnline();
    49. }
    50.  
    51. /**
    52.   Get the Player object
    53.  
    54.   @return Player the player instance
    55.   **/
    56. public Player getPlayer() {
    57. return Bukkit.getPlayerExact(this.getName());
    58. }
    59.  
    60. /**
    61.   Get the current player's location
    62.  
    63.   @return Location the current player's location
    64.   **/
    65. public Location getLocation() {
    66. return this.getPlayer().getLocation();
    67. }
    68.  
    69. /**
    70.   Retrive the current Team Membership associated with the current TeamPlayer
    71.  
    72.   @return Team Membership
    73.   **/
    74. public Team getMembership() {
    75. return this.membership;
    76. }
    77.  
    78. public String getTeamName() {
    79. return this.getMembership().getName();
    80. }
    81.  
    82. public void setMembership(Team membership) {
    83. this.membership = membership;
    84. }
    85.  
    86. }
    87.  


    Code:java
    1.  
    2. public enum TeamAssignment {
    3. NONE("Unassigned"),
    4. BLUE("Blue"),
    5. RED("Red");
    6.  
    7. private String name;
    8.  
    9. private TeamAssignment(String name) {
    10. this.name = name;
    11. }
    12.  
    13. public String getName() {
    14. return this.name;
    15. }
    16. }
    17.  


    Code:java
    1.  
    2. public abstract class Team {
    3.  
    4. private TeamAssignment teamAssignment = TeamAssignment.NONE;
    5.  
    6. public Team(TeamAssignment teamAssignment) {
    7. this.teamAssignment = teamAssignment
    8. }
    9.  
    10. public TeamAssignment getAssignment() {
    11. return this.teamAssignment;
    12. }
    13.  
    14. /**
    15.   Get the team's name
    16.  
    17.   @return String Returns membership assignment as string
    18.   **/
    19. public String getName() {
    20. return this.getAssignment().getName();
    21. }
    22. }
    23.  


    Code:java
    1.  
    2. public class TeamNone extends Team {
    3.  
    4. public TeamNone() {
    5. super(TeamAssignment.NONE);
    6. }
    7.  
    8. }
    9.  


    Code:java
    1.  
    2. public class TeamBlue extends Team {
    3.  
    4. public TeamBlue() {
    5. super(TeamAssignment.BLUE);
    6. }
    7.  
    8. }
    9.  


    Code:java
    1.  
    2. public class TeamRed extends Team {
    3.  
    4. public TeamRed() {
    5. super(TeamAssignment.RED);
    6. }
    7.  
    8. }
    9.  


    Code:java
    1.  
    2. public class TeamPlayerManager {
    3.  
    4. private Map<String, TeamPlayer> teamPlayers = new HashMap<String, TeamPlayer>();
    5.  
    6. public boolean isTeamPlayer(Player player) {
    7. return this.isTeamPlayer(player.getName());
    8. }
    9.  
    10. public boolean isTeamPlayer(String playerName) {
    11. // debug
    12. System.out.println("isTeamPlayer: " + playerName + ", result: " + (this.teamPlayers.get(playerName.toLowerCase()) == null));
    13.  
    14. return (!(this.teamPlayers.get(playerName.toLowerCase()) == null));
    15. }
    16.  
    17. public void addTeamPlayer(Player player) {
    18. this.addTeamPlayer(player, new TeamNone());
    19. }
    20.  
    21. public void addTeamPlayer(String playerName) {
    22. this.addTeamPlayer(playerName, new TeamNone());
    23. }
    24.  
    25. public void addTeamPlayer(Player player, Team membership) {
    26. this.addTeamPlayer(player.getName(), membership);
    27. }
    28.  
    29. public void addTeamPlayer(String playerName, Team membership) {
    30. if (this.isTeamPlayer(playerName))
    31. return;
    32.  
    33. this.teamPlayers.put(playerName.toLowerCase(), new TeamPlayer(playerName, membership));
    34. }
    35.  
    36. public TeamPlayer getTeamPlayer(Player player) {
    37. return this.getTeamPlayer(player.getName());
    38. }
    39.  
    40. public TeamPlayer getTeamPlayer(String playerName) {
    41. return this.teamPlayers.get(playerName.toLowerCase());
    42. }
    43.  
    44. public void removeMembership(Player player) {
    45. this.removeMembership(player.getName());
    46. }
    47.  
    48. public void removeMembership(String playerName) {
    49. if (!this.isTeamPlayer(playerName))
    50. return;
    51.  
    52. this.setMembership(playerName, new TeamNone());
    53. }
    54.  
    55. public void setMembership(Player player, Team membership) {
    56. this.setMembership(player.getName(), membership);
    57. }
    58.  
    59. public void setMembership(String playerName, Team membership) {
    60. if (!this.isTeamPlayer(playerName)) {
    61. this.addTeamPlayer(playerName, membership);
    62. return;
    63. }
    64.  
    65. this.getTeamPlayer(playerName).setMembership(membership);
    66. }
    67.  
    68. public Team getMembership(Player player) {
    69. return this.getMembership(player.getName().toLowerCase());
    70. }
    71.  
    72. public Team getMembership(String playerName) {
    73. if (!this.isTeamPlayer(playerName))
    74. return new TeamNone();
    75.  
    76. return this.teamPlayers.get(playerName.toLowerCase()).getMembership();
    77. }
    78.  
    79. public String getTeamName(Player player) {
    80. return this.getTeamName(player.getName());
    81. }
    82.  
    83. public String getTeamName(String playerName) {
    84. return this.getMembership(playerName).getName();
    85. }
    86.  
    87. public TeamAssignment getTeamAssignment(Player player) {
    88. return this.getTeamAssignment(player.getName().toLowerCase());
    89. }
    90.  
    91. public TeamAssignment getTeamAssignment(String playerName) {
    92. return this.getMembership(playerName).getAssignment();
    93. }
    94. }
    95.  


    Code:java
    1.  
    2. // this goes to your head section of your plugin
    3. private TeamPlayerManager teamPlayerManager;
    4.  
    5. // To get access to your TeamManager init it in your onEnable
    6. this.teamPlayerManager = new TeamPlayerManager();
    7.  
    8. // create a static method to get your manager from your plugin directly if you need the same instance
    9. // in all classes OR pass it to the class
    10.  
    11. ...registerEvents(new PlayerListener(this.teamPlayerManager()));
    12. ...getCommand("yourcommand").setExecutor(new YourCommand(this.teamPlayerManager));
    13.  


    After that you can use it as you need.

    Hope that works as intended. I dont have a compiler here so i cant check. If there is a problem just tell me =)
     
    colozz likes this.
  22. Offline

    colozz

    Thank you for your help and thank you for the JavaDoc =)

    But there is some errors in TeamPlayerManager :

    - In the method isMember(String playerName), change :
    Code:java
    1. return this.playerMemberShips.containsKey(playerName.toLowerCase());

    By :
    Code:java
    1. return this.teamPlayers.containsKey(playerName.toLowerCase());


    - Change the method :
    Code:java
    1. setMembership(Player player, Team membership)

    To :
    Code:java
    1. setMembership(Player player, TeamAssignment membership)

    And do the same for setMembership(String playerName, Team membership)

    - You forget the "return" is the method getMembership(Player player)

    - Change the method :
    Code:java
    1. public Team getMembership(String playerName)

    To :
    Code:java
    1. public TeamAssignment getMembership(String playerName)

    And do the same for getMemberShip(Player player)

    - In the method setmembership(String playername, TeamAssignment membership), there is :
    Code:java
    1. this.addTeamPlayer(playerName, membership)

    But the method addTeamPlayer(String playerName) has only one argument

    - In the method


    And in TeamPlayer :

    - In the method TeamPlayer(String playerName, Team membership), "player" cannot be resolvedso there is errors on :
    Code:java
    1. this.playerName = player.getName();
    2. this.playerDisplayName = player.getDisplayName();
    3. this.membership = membership;


    - Change :
    Code:java
    1. private Team membership;

    To :
    Code:java
    1. private TeamAssignment membership;


    - Change the method :
    Code:java
    1. public Team getMembership()

    To :
    Code:java
    1. public teamAssignment getMembership()


    - Change the method public Player getPlayer()
    Code:java
    1. return Bukkit.getPlayerExact(this.getPlayerName());

    To :
    Code:java
    1. return Bukkit.getPlayerExact(this.getName());



    And finally in the main class, what do you mean for "PlayerListener" ?
    It is my main Listener or have I to create the class PlayerListener ?

    I try to correct other little errors and I will tell you them.
     
  23. Offline

    AmShaegar

    Did anyone request those properties like the team to be persistent?

    I did not find it. That would be the class you have to create instead of your CustomPlayer that implements Player.
     
  24. Offline

    lycano

    colozz oh thanks i will change my post. Glad you could fix it by yourself =) I had this done yesturday and was going to seperate team and player object in teammanager and thought "i dont have to do that". Seems i missed correcting that =)

    PlayerListener was an example of how you could use the manager class to demonstrate that you actually would have to pass the Manager to the class to use it internally.

    Also this is a decision you can make on your own. Weither you init it in your main java class or only in one. Depends if you need to use the same instance in different places.
     
    colozz likes this.
  25. Offline

    colozz

    AmShaegar Ok thanks

    lycano I didn't understood how to use the Manager internally but I think I will find how to use what you done, I'm gonna see this afternoon if the code works, thank you =)

    A little error, in your class TeamBlue, you wrote
    Code:java
    1. super(TeamAssignment.RED);


    In your TeamPlayerManager, in the method addTeamPlayer you made :
    Code:java
    1. playerName = playerName.toLowerCase();
    2. if (this.isTeamPlayer(playerName))
    3. return;
    4.  
    5. this.teamPlayers.put(playerName, new TeamPlayer(playerName, membership));

    But the constructor TeamPlayer is TeamPlayer(String playerName, String playerDisplayName, Team membership)
    So we have to write :
    Code:java
    1. this(playerName, Bukkit.getPlayerExact(playerName).getDisplayName(), new TeamNone());


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

    lycano

    colozz i edited my post. Check it for updates =) Also you where on the right track. There was no TeamAssignment return and because i used a mixed up version of an older state you corrected it as good as you could. Nice work!

    But i designed it to always return Team object as you can get the assignemt from there.

    Store TeamPlayers -> Contains Team -> Team can be assigned to be either None, Blue, Red

    To check for Team assignment you can use a switch now as i implemented additional methods to get the assignment from the team object.

    Code:
    TeamAssignment ta = this.teamPlayerManager.getTeamAssignment("Player");
    switch (ta) {
        case NONE:
            // do stuff
            break;
        case RED:
            // do stuff for red team
            break;
        case BLUE:
            // do stuff for blue team
            break;
    }
    
    Hint: This can be used for your rules system. Just repeat the abstraction of Team for Rules and implement it in Team abstracted class.

    Some more examples for the RuleSystem i would use:
    Code:java
    1.  
    2. public interface Rule {
    3.  
    4. public String getName();
    5. public String getDescription();
    6. public boolean isActive();
    7. public void enable();
    8. public void disable();
    9. public void apply();
    10.  
    11. }
    12.  


    Code:java
    1.  
    2. public abstract class TeamRule implements Rule {
    3.  
    4. private String ruleName;
    5. private String ruleDescription;
    6. private boolean ruleActiveStatus;
    7.  
    8. public TeamRule(String name) {
    9. this(name, null, false);
    10. }
    11.  
    12. public TeamRule(String name, String desciprtion) {
    13. this(name, description, false);
    14. }
    15.  
    16. public TeamRule(String name, String description, boolean active) {
    17. this.ruleName = name;
    18. this.ruleDescription = description;
    19. this.ruleActiveStatus = active;
    20. }
    21.  
    22. public boolean isActive() {
    23. return this.ruleActiveStatus;
    24. }
    25.  
    26. public void enable() {
    27. this.ruleActiveStatus = true;
    28. }
    29.  
    30. public void disable() {
    31. this.ruleActiveStatus = false;
    32. }
    33.  
    34. public abstract void apply();
    35.  
    36. }
    37.  


    Code:java
    1.  
    2. public class FriendlyFireRule extends TeamRule {
    3.  
    4. public FriendlyFireRule() {
    5. super("Friendly Fire", "Allows/Disallows friendly fire", false);
    6. }
    7.  
    8. public void apply() {
    9. // do stuff
    10. }
    11. }
    12.  


    The apply() method can be used to implement your logic but this would require you to pass the TeamPlayer object as you might need to set stuff for a player. Or you implement the logic elsewhere and remove execute and use the structure only for message output and stuff.

    colozz i removed displayName from TeamPlayer. Its now fetched via getPlayerExact().

    Also i fixed some bugs
    • where a playerName would always be lowercase
    • isOnline does return null when the player is not online.
    • removed unneeded toLowerCase() calls
    Some methods will return null like getLocation() or getDisplayName() indicating that the player is not online.

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

    colozz

    Ok, I'm gonna correct my code, thanks.

    Ok, so I have a last question to use this code perfectly, how should I implement another property like a class system, with getClass() and setClass() ?

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

    lycano

    If it is a player property just add this to the interface and then to TeamPlayer as method. If its something team specific add this to Team abstract class and if it should be teamRed specific override it there so it does something else.
     
  29. Offline

    colozz

    Ok thank you very much for helping =)
     
  30. Offline

    lycano

    You're welcome!
     
Thread Status:
Not open for further replies.

Share This Page