I’m currently in the process of setting up developer products so players can buy ‘Cash’. To prepare for potential data loss or for the worst case scenario where I am forced to reset all player data, I have created a second datastore to record the amount of Robux spent on developer products. This means if ever have to, refunding players will be possible.
Because this is such a vital feature, I was wondering if other developers would be willing to proofread to code in case of any logic errors:
Also, rather than running a spawn function, I would suggest switching to using RunService.Stepped like so:
Code
local RunService = game:GetService("RunService")
local lastCashDataUpdate = tick()
local intervalBetweenCashDataUpdates = 10 -- In seconds
local function onStepped()
local t = tick()
if t - lastCashDataUpdate < intervalBetweenCashDataUpdates then return end
lastCashDataUpdate = t
-- Now your for loop, which looked like it would work just fine.
end
RunService.Stepped:Connect(onStepped)
I recommend using the event-driven system for two reasons. One is that I find it much cleaner than having an infinite while loop, and the other is that it ties your recurrent systems into RunService, which is meant for that purpose, and steers you away from infinitely running code.
Data isn’t being saved to the datastore every 10 seconds - it’s only saved when there is data needing to be saving, and that only happens when a player purchases cash. I chose 10 seconds over 60, for example, because if someone purchases cash right before a server shutsdown, then that should be enough time for it to be saved.
So, yes, it is good to make sure you save data before the server shuts down - but that’s sort of what game.OnClose is for.
And when you really think about it, no, the loop shouldn’t be infinite. Once the RunService stops, once the game stops, then so should your updates. Now, yes, you’d be right in saying that the server handles that for you. But I would argue it is better to always design your code such that the server isn’t shutting it down mid-execution, which would be the case for an infinite loop.
Also getting back to the original question, is there any reason for the method you’re using? Why not just save the players data every time they purchase more cash?
I agree that I should also save data when the game closes, thanks.
Regarding RunService, I don’t have a huge understanding of it, but why would it matter if your code keeps running when RunService ends? The game will close eventually, and no one will be able to join that server, so why would it be a problem?
It can be a problem, rarely, because you don’t have any assurances as to when the code stops. At least with connecting to RunService events, you know that the last iteration of your code will happen when the game stops running.
As far as I know, an infinite loop doesn’t cause any actual technical problems. I just suggest avoiding them for cleaner code and to give yourself more assurances.
:UpdateAsync has a ‘cooldown’ of 6 seconds. If a player was to buy 2 lots of cash within 6 seconds, then the request would be throttled. Making data save every 10 seconds prevents this, and is also less intensive on the datastore
I mean, you could do that, I would not. wait(...) does not guarantee any actual amount of time, it just guarantees a minimum amount of time. Honestly my problem with infinite loops is wait(...)–I avoid that function whenever possible.
Also just a tip, @ForeverHD, you can put your code into a code block on here by pasting it in with one indentation to the right, or by doing ``` to start and end the code.