Run code in background when player joins.

Discussion in 'Plugin Development' started by ZudoHackz, Jul 12, 2014.

Thread Status:
Not open for further replies.
  1. I am really stuck. I want to send an HTTP request when a player joins my server, and it works fine. The only problem is that the player is stuck in limbo while the request is being executed, which is annoying. I need to access the player's name to send in the request, but I want it to run in another thread. Is this possible?
     
  2. Offline

    TheMcScavenger

    The easiest solution I can think of right now is adding a runnable when the server starts, executing a piece of code for every player in a list. When a player joins, add them to that list, and when the code is executed, remove them from the list. That way, they're only "stuck' until their name is added to a list, which takes .001 seconds.

    Code:java
    1. public static List<Player> players = new ArrayList<Player>();
    2.  
    3. public void onEnable(){
    4. Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable(){
    5. public void run(){
    6. for(Player p : players){
    7. // Your Code Here
    8. players.remove(p);
    9. }
    10. }
    11. }, 0, 20);
    12. }
    13.  
    14. @EventHandler
    15. public void onJoin(PlayerJoinEvent event){
    16. players.add(event.getPlayer);
    17. }


    Of course you would use an interval that is appropriate for the task you're executing, which could be 1 second, 5 seconds, or even 5 minutes depending on the task.
     
  3. Offline

    ResultStatic

    ZudoHackz im pretty sure its safe to use player.getName() async. i did it on my server for like 4 months without any problems. i used it for sql. lol the first time i ever used sql i wrote everything so it stored the player's kit in the database. i had no clue what i i was doing. then it would retrieve it on pretty much every player event. it was such a mess. the server would freeze every couple seconds until the request finished. always do that stuff in async.
     
  4. Offline

    fireblast709

    AdamQpzm I don't have access to GameProfile atm, but the field is final in EntityHuman, which makes it thread safe till that point. (If anyone can check GameProfile for me, thanks in advance)
     
  5. Offline

    hankered

  6. Offline

    chaseoes

    Store their name as a final string variable, and you can access that from another thread.
     
    Dragonphase likes this.
  7. Offline

    TheMcScavenger

    While there's a lot of people that whine about storing players causing memory leaks, they're not severe enough to actually matter. Storing players works perfectly fine, and there's no reason why anyone shouldn't.
     
    xTrollxDudex likes this.
  8. Offline

    Necrodoom

    TheMcScavenger Because storing name/UUID is just as easy and is less error prone/memory leaking.
     
  9. Offline

    Garris0n

    Use their UUID.

    You have a future in politics.
     
  10. Offline

    Double0negative

    There are a lot of reasons why you shouldn't blindly store players. One being memory leaks, another being it wont necessarily work as expected (Player leaves and rejoins, now your stored Player object is invalid and wont be the same). However, as long as you clean up after yourself, using Player Objects will be the faster than any of these other methods that people like to preach (looking up by name or UUID for example)
     
  11. Offline

    hankered

    Garris0n
    Woops, sorry I haven't updated to UUID's yet. Totally forgot hah.
     
  12. Offline

    TheMcScavenger

    Like I said, you don't even notice the "memory leaks".

    In most cases, you'll be storing the players only if players are online, as the data is lost anyways on server restarts / reloads, meaning when a player leaves you just remove them from the list ;)
     
  13. Offline

    Necrodoom

    TheMcScavenger These things add up. If you cant take the time to simply use a UUID and make your code better and cleaner, then you shouldnt code it in the first place.

    Telling people to use player objects because "you dont notice the problems it causes anyway" is a stupid thing to say, because not only people may not realize that storing player is disadvantageous and problematic when it comes to store for longer terms than a player's session, but also shows laziness, as you cant bring your self to store the UUID despite it being a single change.
     
  14. Offline

    daavko

    TheMcScavenger What if server doesn't restart for a week? When you have player, who disconnects while in nether and he is last player in there, server tries to unload that world, but can't because you still have player instance in your list. Same happens when player is last on server and disconnects - world can't be unloaded. (unless you remove player from that list on PlayerQuitEvent)
     
  15. Offline

    TheMcScavenger

    It's a change in every line you used the method I described. So what if I'm lazy? I can code if I want, and there's not a single person on earth that can stop me. If you don't like it, that's your problem <removed> ;)


    Read a post before you respond to it. I already said you have to remove them on quit.


    [edit by JaguarJo: removed inappropriate comment. Adding a winky face does not magically make that kind of statement okay.]
     
  16. Offline

    Necrodoom

    TheMcScavenger if you want to use bad practices, sure, but dont come here and tell me that your method works fine, because "its just a little memory leak" doesnt impress anyone.

    Also, what if you want to deal with a player while he is offline? Yes, you would store his UUID.
    What if youd want to store for long terms? Youd store his UUID. But ofcourse, your recommendation doesnt cover that.
     
    AdamQpzm and Garris0n like this.
  17. Offline

    Garris0n

    I couldn't care less if you run around doing stupid things, just don't teach others to do the same.

    Now that was just immature.


    [edit by JaguarJo: removed offensive comment from quote]
     
    AdamQpzm likes this.
  18. Offline

    AoH_Ruthless

    ....


    [edit by JaguarJo: removed offensive comment from quote.]
     
  19. Offline

    teej107

    His statements are as mature as his coding practices. Now I know not to use any plugins developed by him because I don't want to risk a server to laziness.

    Yes, you can prevent memory leaks by removing the player from a list when they leave but I prefer to be safer then sorry. Using UUIDs or player names to access a Player is pretty easy.
     
  20. Offline

    Double0negative

    Using UUID's does not make your code cleaner or better. It is more or less the "Easy way out, catch all solution" and allows you to not have to clean up after yourself at the expense of speed. Sure, what this other dude keeps saying is the totally wrong way to go about it, for many reasons, but just blindly telling people to use UUID's isn't necessarily correct either.
     
  21. Offline

    Garris0n

    It's a simpler way to explain it to those who are new. Kind-of like how you might teach a new Java coder to use an Array when an ArrayList would technically be better.

    Really, weak references are the way to go.
     
    Double0negative likes this.
  22. Offline

    hintss

    I teach people to use ArrayLists before Arrays...
     
  23. Offline

    Garris0n

    They should understand how the underlying Array actually works before using the "easy way". Really, it would be best to have them write their own (simpler) ArrayList implementation before telling them about it. That's what a Java course I took did.
     
    AdamQpzm likes this.
  24. Offline

    mythbusterma


    So your code is absolutely, in every way, perfect? Good to know I should never recommend any plugin written by you. Do you really think new developers will clean up after themselves? Forgetting to remove references to Player objects has SERIOUS consequences that DO matter, for example not unloading worlds, chunks, etc. that take up a large amount of memory, just for starters.

    What if there's a glitch in Bukkit, Spigot, MCPC, anything that causes a PlayerQuitEvent to not be fired? You're going to look mighty silly when your plugin is still holding on to that Player object because you're too good for best practice.

    Double0negative

    Blindly telling them to use UUIDs is the only way they're going to listen and produce halfway decent code.

    Given, Garris0n is right, weak references are still by far and away the best way, but saving that, store their UUID just to be safe.
     
  25. Offline

    Double0negative

    Looping thought all players every time they want to get a player object is not decent code. But I guess its better than memory leaks... because you know, telling them they need to clean up by adding a few extra lines is too complicated.
     
    Saladoc likes this.
  26. Offline

    mythbusterma

    Looping over the players is a relatively cheap operation compared to:


     
  27. Offline

    fireblast709

    Weak referencing + manual cleanup ftw. Especially when you need to get the Player object, it's currently a nice efficiency boost because neither CB nor NMS use a Map for players (well it will always be faster than using getPlayer() even when its backed by a Map, but it will matter less with O(1) practical running time)
     
  28. Offline

    xTrollxDudex

    Lol ladies calm your thingies down.

    Has everyone forgotten that OP only wants to have the player on PlayerQuitEvent? Obviously, storing the player reference is OK here because when the method returns, the stack frame becomes inaccessible, hence, all of the objects added to the stack are GCd :) simple, lets not argue anymore.

    fireblast709
    HashMap takes around 25 nanoseconds to retrieve for any length of the underlying length of the array, which ArrayList is O(n) for any lookup-check iteration.

    That reminds me, I should make a weakref map for my lib...
     
  29. Offline

    fireblast709

    Optimalization is optimalization ;). Especially now while the players are stored in a List you have something to gain (assume we have a list of all player names to get a Player object from, geez that O(n^2)).

    But yea as I mentioned in my post, when Minecraft or Bukkit finally move to an UUID->EntityPlayer Map as seen in the CB comments, it would hardly matter whether you use a Player reference or a UUID.
     
Thread Status:
Not open for further replies.

Share This Page