Async Player Name to UUID without directly using IO?

Discussion in 'Spigot Plugin Development' started by HyperPlay, May 18, 2016.

  1. Is there any thread-safe method to do this without calling the Mojang API, as I want to benefit from the caching on the server? The player would likely be offline but would've joined the server before.
     
  2. synchronized access? Aka the synchronised keyword maybe.

    Gesendet von meinem Nexus 5 mit Tapatalk
     
  3. That is not how synchronization works, it would have to already be synchronized in Spigot/CraftBukkit. You can't just add synchronized to your plugin code and expect it to be thread-safe, otherwise asynchronous tasks would be a lot easier.
     
  4. wat

    Nope.
     
    • Agree Agree x 1
  5. Run a synchronous task inside the asynchronous task.
     
    • Winner Winner x 1
  6. If you don't want to call the Mojang API, just call the getOfflinePlayer(name). The uuid of the OfflinePlayer will be an offline uuid if they have never logged in before, or if your server was in an offline mode when they logged in.

    If you want to make sure it's not an offline uuid (after knowing they have indeed logged in once before):
    Code (Java):
    OfflinePlayer oplayer = Bukkit.getOfflinePlayer(name);
    UUID offlineUniqueId = UUID.nameUUIDFromBytes(("OfflinePlayer:" + oplayer.getName()).getBytes(StandardCharsets.UTF_8));
    if (offlineUniqueId.equals(oplayer.getUniqueId())) {
      // offline uuid
    } else {
      // mojang uuid, perform whatever
    }
    It's not recommended to call Bukkit methods in async tasks.
     
    #6 CraftedFury, May 19, 2016
    Last edited: May 19, 2016
  7. Bukkit#getOfflinePlayer(String) is not thread-safe.
     
  8. Call that code in a synchronized (lock) or synchronize a method that gets their UUID, whatever works.
     
  9. As highlighted above,
     
  10. Are you really saying that synchronized BukkitRunnables are not thread-safe? wat.
     
  11. He's saying that putting Bukkit.getOfflinePlayer() inside of a synchronized block is not going to make it thread safe.
     
  12. No. I am saying slapping on synchronization statements around code which uses Bukkit#getOfflinePlayer(String) will not make Bukkit#getOfflinePlayer(String) thread-safe. Doing so would show extreme ignorance to how the JMM works.
     
    • Agree Agree x 1
  13. You could save/load/manage a store of uuids and usernames yourself, maybe to a json file or something
     
  14. @CraftedFury neeuuuwwww, getOfflinePlayer needs to go through all player files to find one with the correct name (if names are saved with uuids in a single file, nvm, but im currently on my phone so I cant check). Just use the Mojang API then
     
  15. Maybe try using the usercache.json ?
    Watch out because it might brick your server.
     
  16. whats not thread safe about it ?
     
  17. Glanced over the code, here two some issues I think it has:
    - Fetches GameProfile from UserCache, but UserCache is backed by non-synchronized HashMap
    - Accesses non-synchronized list containing online players

    These are both reads, so the issues are relatively small. It does try to modify a map of offline players as well, but it does so safely. All in all, it's probably thread safe. Saying 100% for certain if the two non-synchronized reads could cause issues would require knowing a lot more about Spigot's internals than I know.
     
    • Like Like x 1
  18. Calling Bukkit#getOfflinePlayer for a player who has possibly never joined before will block the main thread until Mojang responds as far as I know, already thought of this.
     
  19. https://hub.spigotmc.org/jira/browse/SPIGOT-461

    Someone reported it does cause exceptions, but the issue has been marked resolved with no comment or link to the fix commit, not really sure about this. I'll probably just have to use the Mojang API though.
     
  20. You could load the usercache.json file yourself. As long as you are just reading a file you shouldn't get any kind of problems even if it's currently being modified/saved.