Caching player names / UUIDs

Discussion in 'Bukkit Discussion' started by !Phoenix!, Apr 16, 2014.

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


    Hey there,

    Some plugins (I am affected myself) need to have access to player names and their UUIDs 24/7 and not only when the player in question is online.
    Example: A plugin that allows to look up who changed block X the last time. If I check a block I would like to be presented a player name and not an UUID. Therefore the plugin has to either (1) look up the player name every time at Mojang's servers (No!) or (2) cache the players name. The player is offline in this case.

    As there are quite a lot plugins that would need to have access to offline player names I think it would make sense to have one central instance that does the caching and allows lookups. Instead of each plugin having its own list of cached usernames. What do you think?
    It would be great if Bukkit could do that, but I am not sure if they would accept it as "their business". Even though I bet a lot of plugins would make use of it.
  2. More complex and serious plugins might need both ways look up both from cache and from Mojang (for offline players, for the paranoid also for online players e.g. for async pre-login, or just on a regular basis for consistency checking and UUID-Zero-Day-detection).

    I'll write my own, unless i keep posting too much.
  3. Offline


    I think it's already being done. EvilSeph mentioned in one of his PSA replies that they were storing the last known username, that would indicate at some point they will make that available to the API. In the short term I'm storing both, but I agree if dozens of plugins do this, it's redundant and wasteful.

    EDIT: Actually based on the description of the dev build Javadocs, I think they are already doing this. It says "null if we have not seen a name for this player yet" which would mean they are using the last known (as opposed to fetching the name, like they were with UUID in 1.7.5).
  4. Offline


    Additonally to the lastKnowUsername being stored in the player data files there is also the 'usercache.jason' file since v1.7.8+

    This seems to cache playername<->uuid mappings for about one month, already built in into minecraft. Bukkit's getOfflinePlayer also seems to use that cache if it has looked up a valid uuid for a playername.
  5. Offline


    This caching is basicly useless as you will always get a UUID of a name that may be outdated for days.
    It's not a reliable system at all.
    The bad thing is: There's no way to circumvent this because you simply have to get the "UUID by name" whenever you handle offline players.
    At least if you do not use the UUID in player chat or on signs instead of the name now - which is unrealistic.
    Because we are humans and not machines who are good at handling 32 digit numbers.
    So there's a weak spot which is inherent to the new system: The human aspect.
    I guess Mojang has not considered this yet with their beautiful technical solution.... :confused:
  6. Offline


    Alshain01 Good to know. Would be great if that is actually the case! Thank you for the info.

    CubieX The idea here is to be able to provide names instead of IDs all the time. Let's say I have the ID 1234 stored in my plugin and I want to make an announcement like "<guy> has not been online since two days now". Then I can look up the cached player name of 1234 instead of having to give the ID. Yes, it might be that the name changed in the meantime, but as this is not going to happen too often and the name should also be blocked for some time this would be an "okay" solution.
  7. Offline


    Did you know Bukkit's getOfflinePlayer() already uses a cache when you pass a player name?

    So I imagine it should be pretty quick and convenient way to go about it. If nanoseconds are important to your use-case, you should build your own cache. I.e. at server load time populate an ID, map map...

    static ConcurrentHashMap<String, String> playerIDMap = new ConcurrentHashMap<String, String>();

    Then during player logins, update that player's current name by ID.

    I don't see this making sense for Bukkit to add to their API though. Reason why is imagine all sorts of player properties that are useful to lookup. You wouldn't want separate hashmaps for every one. Easier to have a hashmap at the gameprofile level (which is what getOfflinePlayer does).

    PS: As I was browsing the Bukkit source code for this, I noticed there are comments there interestingly, where they talk about using the new map.

    1. // TODO: In 1.7.6+ this should use the server's UUID->EntityPlayer map
    2. public Player getPlayer(java.util.UUID id) {
    3. for (Player player : getOnlinePlayers()) {
    4. if (player.getUniqueId().equals(id)) {
    5. return player;
    6. ...

    I assume this is to improve performance. A hash lookup is faster than looping through a collection.
  8. Offline


    That's exactly what Alshain01 mentioned before. So my "problem" is actually already solved.

    I do not think the few nanoseconds saved would be worth it compared to getting the name via OfflinePlayer. It is redundant, takes up memory and might get out of sync if a player logs in while the plugin is disabled.

    If you do it you might want to use the UUID object instead. It's more handy and takes up less ram than the String version.

    So you really think having a way to get the player name from an UUID is something not worth it to be added to the Bukkit API? Even tough it is already implemented in OfflinePlayer?
Thread Status:
Not open for further replies.

Share This Page