Per Player Variables?

Discussion in 'Plugin Development' started by pers2981, May 1, 2012.

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

    pers2981

    Hey there,

    I'm looking for way of storing data per player. What I mean by this is, say i'm making a super pick axe plugin that activates when you type /sp and Bill just toggled it. How would I make it so that only Bill has super pick enabled, Is there a way of saving a variable per player as in billsuperpick = true but ericsuperpick = false?

    Regards Jacob
     
  2. Offline

    CorrieKay

    yes, have a list of players, and whenever they try to break a block, if theyre in the list, break the block naturally.

    edit: whenever they type the command, add them to the list if theyre not already in the list.

    if theyre in the list, remove them. both ways, notify them of their new current superpick status
     
  3. Offline

    marky1991

    I'd probably have a list of players that have superpick enabled. (You could alternqatively use a dictionary (HashMap) if you like that better. (It's theoretically faster given infinite players. Whether it's faster at the number of players seen in practice, I can't say. I'd probably stick with the list.))

    Code:
    List<Player> enabled_users = new ArrayList<Player>();
    enabled_users.add(bill);
     
    ...
    if (enabled_users.contains(player)) {
        do_some_cool_stuff();
    }
    edit: Oops. Closed the outer parenthesis in my first paragraph.
     
  4. Why a Map if you just want to store a boolean? Use a HashSet! Also never save the player directly, just save its name:
    Code:
    HashSet<String> enabled_users = new HashSet<String>();
    enabled_users.add(player.getName());
     
    ...
    if (enabled_users.contains(player.getName())) {
        do_some_cool_stuff();
    }[/syntax]
     
  5. Offline

    marky1991

    Hmm, I agree. A set is semantically better than both a list and (the admittedly awkward) dictionary.

    Why is it bad to use the Player as a key instead of his name?

    edit: Asked why using Player as a key is bad.
     
  6. May bring memory leaks, example:
    1. Player enables the mode and get stored in the list.
    2. Player logs off. He's still in your map so the Java GC can't remove it from RAM.
    3. Another plugin wants to unload the world the logged off player was in. Java GC can't remove the it from RAM cause it's till needed by the Player object in your map.
    Another thing is that the hash of the Player object is able to change (don't ask me why) from the first to the second time asking for it. a Hash[Map/List] compares the hash for contains. CB Code from CraftPlayer:
    Code:java
    1. private int hash = 0;
    2.  
    3. @Override
    4. public int hashCode() {
    5. if (hash == 0 || hash == 485) {
    6. hash = 97 * 5 + (this.getName() != null ? this.getName().hashCode() : 0);
    7. }
    8. return hash;
    9. }

    for the function equals() (used by lists to compare) other things may occur, but I don't want to crawl that deep through CB code now.

    Long story short: You should never save bukkit objects over time, cause of memory leaks and weird bugs caused by hashCode() and equals() changes. Also other things may apply, but for that we need more advanced devs. ;)
     
  7. Offline

    marky1991

    Is a player's name allowed to change? (Either way, hashing based on the player's name is just as breakable. A player's hash only changes when the hash of his name changes)

    Thanks for explaining about the memory issue though.
     
  8. Offline

    CorrieKay

    No, a players name is not allowed to change. his/her display name, however, is.
     
  9. marky1991 Sure? the hash is 0 when the object get's created. You save it in the map, it get's generated and returned, now let's say it's 485.
    You call compare. Cause it's 485 it get's regenerated and returned: You got false.
    I don't know why this is the case (what string produces the hash code 485?)
     
Thread Status:
Not open for further replies.

Share This Page