-- Check how many if it's beyond 4 million then probably reset it
local dataCounter = HttpService:JSONEncode(PlayerProfile)
print(Player.Name.." has "..string.len(dataCounter).." in their Data")
tables cannot be cyclic - Server - StatsService:194
14:19:27.223 Stack Begin - Studio
14:19:27.223 Script 'ServerStorage.Aero.Services.GameStats.StatsService', Line 194 - function PlayerAdded - Studio - StatsService:194
14:19:27.223 Stack End - Studio
what?
Output
ServerStorage.Aero.Services.GameStats.StatsService:151: attempt to index nil with 'Data' - Server - StatsService:151
14:22:07.819 Stack Begin - Studio
14:22:07.819 Script 'ServerStorage.Aero.Services.GameStats.StatsService', Line 151 - function KickPlayer - Studio - StatsService:151
14:22:07.819 Script 'ServerStorage.Aero.Services.GameStats.StatsService', Line 189 - function PlayerAdded - Studio - StatsService:189
14:22:07.819 Stack End - Studio
Code
local function KickPlayer(Player, PlayerProfile)
if Banned[tostring(Player.Name)] then
Player:Kick("You were banned automatically!")
elseif PlayerProfile.Data.Stats.Banned == true then
Player:Kick("You were banned by an Admin!")
else
print(Player.Name.." is allowed in the game!")
end
end
Caller of Function
local function PlayerAdded(Player)
local PlayerProfile = GameProfileStore:LoadProfileAsync(
"Player_"..Player.UserId,
"ForceLoad"
)
-- Baically Preventing Item loss and Duplicates or as Session Locking
if PlayerProfile ~= nil then
PlayerProfile:Reconcile() -- if there is something missing then fill it up
PlayerProfile:ListenToRelease(function()
-- might have loaded on another server
Profiles[Player] = nil
Player:Kick()
end)
if Player:IsDescendantOf(Players) == true then
-- woo hoo yes
Profiles[Player] = PlayerProfile
print("Data successfully Loaded!")
KickPlayer(Player, PlayerProfile)
else
-- oops
Player:Release()
end
else
-- Couldn't load it
Player:Kick()
end
-- Data Handling is done check if they are banned
KickPlayer(Player)
-- Check how many if it's beyond 4 million then probably reset it
local dataCounter = HttpService:JSONEncode(PlayerProfile)
print(Player.Name.." has "..string.len(dataCounter).." in their Data")
end
The Profile object is cyclic because it has a reference to a ProfileStore object that has a reference back to the Profile. On the other hand, Profile.Data is exactly what you set it to be and is not even allowed to be cyclic, so you can JSON encode it.
You will have to implement that yourself. One way to do it would be to have a container class for Profiles that has setter methods. Alternatively, you could use loleris’ new ReplicaService, which kind of builds that in for you.
ProfileService doesn’t have an Set() method, alternatively if values like this Name = Value have an .Changed() then it basically solves all my problems or even better aa function that detects whether an table is updated!
…Please read my original reply. I believe I already answered that.
Anyways, personally, I believe that a custom change signal is more useful. Using Rodux as an example, it has a changed signal that simply gives you the old state and new state, making you check against old values to find differences. Although this isn’t necessarily a downside, custom signals for changes are more readable as opposed to a one-size-fits-all change signal.
If you’re comfortable with making Lua-style classes, you could create a pretty simple solution easily. In the constructor, give it the Profile and create the signals you need (eg: CashChanged, etc.). Then, just add setter methods that set the value and fire the appropriate signal.
I noticed that the data takes over 25 seconds (roughly 30) to load. I don’t have a wait on the releases, but I do realize that the following is printed:
[ProfileService]: DataStore API error (Store:“PlayerData”;Key:“Player_81553363”) - “ServerScriptService.dataRetriever.ProfileService:548: attempt to index nil with ‘UpdateAsync’”
I also realize it gets stuck when I run LoadProfileAsync
Recommendations?
local profile = GameProfileStore:LoadProfileAsync(playerID, “ForceLoad”)
^ where player is “Player_”…player.UserId
This is the really basic implementation of it using ForceLoad, I tried with Steal but it is the same. Noticed sometimes it is fast as lightning then occasionally it is taking a moment. I thought it had something to do with the release but then I ruled that out because leaving causes the release, without any wait.
30 second load is usually the cause of not releasing. You have to be 120% sure your code gets to the point where it releases the profile, every time. Do prints and do some offline server testing.
[12/20/2020] - Studio bug fix (Online mode is not vulnerable to this)
Fixed a race condition where a profile could be loaded before the live key access check finishes - this bug was introduced with the no yield on require update two days ago. This can be the cause of errors in studio testing.
Quick question - is it possible to bind functions to some kind of event that occurs when data is changed, such as with DataStore2’s :OnUpdate callback?
Just getting into ProfileService and loving the flexibility and scalability!