Solved Is this system good?

Discussion in 'Spigot Plugin Development' started by ConfusedMan, Oct 16, 2021.

  1. I'm looking for opinions on my system. I have never had a mass amount of players before so I struggle to understand and would love someone with experience to provide their opinion.

    My system is regarding the saving and managing of live player data.

    Basically, I use a data class in local memory. This is loaded on first entry to the server through SQL (Hikari CP). When changes are made, two things happen: (1) the local value is updated, (2) an ASYNC SQL update is sent to update the value in the database. This means that the new data can be accessed instantly and also that the value is saved not long after in the database to protect it from loss due to crashes etc.

    I don't know if this sounds basic, or complex, or anywhere in between.

    Am I doing this right? Any advice would be much appreciated :)
  2. I think I wouldn't do this better either :D
    • Funny Funny x 1
    • Friendly Friendly x 1
  3. That sounds quite right. When a player joins however, do you load his/her data async as well? If not, you should really switch to doing so.
    • Friendly Friendly x 1
  4. Sounds pretty much alright. However, it's generally not necessary to sync the data to the DB each time changes to the cache are made. You can just leave the data cached and update them when the player quits and periodically in between to prevent data loss on server crashes. Just make sure data from the DB is never accessed/updated in a synchronous context unless you have a good reason to do so. Other than that, this sounds like a pretty good approach.
    #4 Sxlver_, Oct 16, 2021
    Last edited: Oct 16, 2021
    • Agree Agree x 1
    • Friendly Friendly x 1
  5. This. I do it as follows:
    Async load playerdata from DB whenever a player connects
    Async store playerdata in DB whenever a player leaves
    Sync store playerdata in plugins' onDisable method (PlayerLeaveEvent isn't thrown when the server shuts down)
    [Optional] Periodically run an async task that loops through all online players and updates playerdata in DB
    • Friendly Friendly x 1
  6. Thank you all for your help! I am pleased to hear it's a good system, I was worried!

    Just in response to this - I don't currently but would love to switch to this. How might I acomplish this? Would I load the data in an async join event instead of PlayerJoinEvent? Such as AsyncPlayerPreLoginEvent? Or am I way off base haha.

    Many thanks
  7. What do you use to attach playerdata to a player? PDC? Metadata?
    You can get the name and UUID from AsyncPlayerPreLoginEvent, so you can indeed fire your query from there. However, the player object is not present at that point (as the player isn't logged in yet) so you would have to store the data somewhere and then attach it to the player after both the query and the actual join have completed.

    Not sure if it's worth the hassle tho. I personally use the PlayerJoinEvent. If your database is local, I don't think it'll make a noticeable difference.
  8. Thanks buddy.

    Yeah, my database is local and we have good resources so I assume the delay shouldn't be huge - though I would like to employ an async method if I can. I don't currently attach the player's data to the player - I simply use a data class which can be found from a central map of UUID, data class.

    Is this bad? Am I about to get roasted? :p
  9. Oh, I see. I personally like to work with the PersistentDataHolder API because it allows storing data directly in a players PersistentDataContainer (that's what I meant by PDC).

    Nothing wrong with doing it your way tho. Whether you can use the AsyncPlayerPreLoginEvent depends on what you use in your data class to match data to a player. If you do it via UUID or name, you can easily move it to that event. Make sure to only load the data if the login result is ALLOWED.
    • Agree Agree x 1
  10. Thank you so much for the reassurance, I'm not great at this stuff so glad to hear it's going okay. As far as I can tell it should be fine to move to that event, many thanks for your input and tips :)
  11. I would use the PlayerJoinEvent, as it cannot be cancelled like AsyncPreLoginEvent and PlayerLoginEvent, and you can also recieve the Player object from it. With that, you can call a method that uses Bukkit's scheduler to run an async task that will load data from your database, then create a cache like you have been doing.
    • Like Like x 1
    • Agree Agree x 1