How can I yield a function in a server script per player?

Hello, I am currently making a datastore script that will save the players hatched data, as well as their inventory. I thought that a good way of doing this is checking if the values aren’t 0, and they actually changed from the last time :SetAsync() was ran. I created 4 functions, 2 to save and load hatched data, and the other two for the inventory. Since there is a limit on the amount of requests I can make per minute, running these functions at the same time will most likely hit that limit. I thought of using a debonce, but I am afraid if two users join the server at the same time, or one is in the process of loading whilst the other user joins. The datastore will either forget about the other player, or hit the request limit. Is there any way to create a debounce on a server script that yields a script per player? Thanks!

Also, I don’t think I’ll need to provide these functions, but if needed please let me know and I’ll send them.

In my implementation I simply loaded all of a player’s data into a big master table when they joined, and only saved it when they left or after about 30 seconds had passed (autosaving) That way you never have to worry about resetting data to the datastore, it’s all handled in the background while you update the information you have on the player in the big data table.

1 Like

Thanks, are you able to explain this a little bit more I kind of don’t understand (sorry i have a small brain)

The inventory is a GUI. So I guess you should use LocalScript maybe… I don’t know too much as I’m not good with DataStoreService

Edit: I didn’t notice the other replies. Lol.

1 Like

I could use a local script but then again exploiters can mess with the code so they can give themselves whatever they want, thats why I wanted to do this on the server instead of the client. Also I’m pretty sure datastores only work on the client.

1 Like

The basics of the system I described are as follows:

First you setup a ModuleScript, and in it you create your datastore and define a table to store all of the playerdata, preferably named PlayerData or something similar. Then you define two functions: GetAsync and SetAsync. These are basically wrapper functions which are the same as your normal DataStore:GetAsync and such, except here you’ll implement retry logic and error handling, etc. Next, you define two more functions, Get and Set which are for getting and setting data in your PlayerData table, NOT your datastore. This allows you to treat the table as your actual datastore, even though it’s not. Next, you should setup three event connections. The first of which is a PlayerAdded connection where you call the GetAsync you defined earlier to get the player’s data from the datastore, then you call the Set with the player’s UserId and the data you got from getasync. This gets the data from the datastore and puts it into the playerdata table, so now you never have to refer back to the actual datastore to get that information. We call this caching your data. The second connection is a PlayerRemoving connection where you call Get to get the player’s data from the PlayerData table, then call SetAsync to set that data to the Datastore. After that you can erase the player’s data from the PlayerData table entirely, as it should be safely secured in the datastore. The third conection is a BindToClose connection, which fires when the game is about to close. In here, you do exactly what you did in the PlayerRemoving, except you now do that for every single player, since every player is removing. After you’ve done the event connections, you setup a while loop in a coroutine (At least that’s how I did it, you’re welcome to use some other method) which waits a set interval ( which I call AUTOSAVE_INTERVAL and usually set to something like 30 or 60 seconds) and then after the set interval is waited it saves the data of all the players stored in PlayerData. It does this the same way your BindToClose connection does, except it doesn’t remove the player’s data from the PlayerData table. This ensures that even if your game goes down, the player’s data is saved as recently as possible to ensure minimal data loss. Then at the end of the module you return a table containing the function Get and Set to allow other scripts to require the module and retrieve data from your PlayerData table.

that’s pretty much it for the basics of how I design my Datastore systems, but there are some more cunning and advanced tricks that I use such as messagingservice failure handling, but that’s a little too much for this post.

Hope this helped a little bit!

1 Like

Will it not be BindToClose instead of BindToclose?

Yeah, small spelling mistake sorry!

1 Like