Save your player data with ProfileService! (DataStore Module)

I keep getting this issue whenever I try to require the DataManager:

ReplicatedStorage.ProfileService.ProfileService:1591: [ProfileService]: profile_store_name must be a string

I found the issue I used the : operator opposed to . when I tried to call GetProfileStore()

2 Likes

Im getting this error trying to save string values : invalid argument #3 (string expected, got nil) (I fixed it somehow it was remaining old tables)

1 Like

So for a game, not necesarrily mine, and to be clear, I am posting for myself, it crashes at random, I’m wondering if there is a way to utilize profile:IsActive() and Locked and Active updates (No clue what those are) to retrieve this lost data.

I BELIEVE ProfileService doesn’t keep any backups. I think it does have its own data safety mechanisms, but it doesn’t keep backups or anything about past data. (From what I know)

Not sure if anyone else has asked, is it probably a safe idea to keep Profile Service in one script to handle everything and use BindableEvents to invoke requests from other server sided scripts?

Or is there a method of tapping into the Profiles table on one from another server script.

I would suggest using a “Handler” module. This module loads data on player join and Releases the profile on player leave. Inside that module you can have functions that add data for a certain player. Something like this:

-- Get the data object of a player (will yield until data is available)
function dataManager.GetData(player)
	local profile = CachedProfiles[player]
	while not profile do
		profile = CachedProfiles[player]
		game:GetService("RunService").Heartbeat:Wait()
	end
	return profile.Data
end

-- Set the saved data to something
function dataManager.Set(player, dataKey, newValue)
	local profile = CachedProfiles[player]
	if profile and profile.Data and profile.Data[dataKey] then
		profile.Data[dataKey] = newValue
	end
end

-- Increment a stored number with another number
function dataManager.Increment(player, dataKey, increment)
	local profile = CachedProfiles[player]
	if profile and profile.Data and profile.Data[dataKey] then
		-- Check if both values are numbers
		if typeof(profile.Data[dataKey]) == "number" and typeof(increment) == "number" then
			profile.Data[dataKey] += increment
		end
	end
end

You require this “Handler” module on whatever (server)script you want to modify a player’s data.

Hi,
is there any event or a way that would invoke a function right away after data is saved or auto saved?

No - ProfileService prevents you from performing final modifications to data before / after saving because 99.9% of the time it’s going to be a redundant or flawed feature. Profile.Data must represent data that will be saved immediately after you suddenly lose access to the profile at any random time (server crash, profile being loaded on another server) - this ensures minimal progress loss as opposed to only saving data when the player leaves.

You can create your own ModuleScript that creates the Profile objects for players. When you require() a module, it returns a reference to the value the module script returned the first time you required it - It means that ModuleScripts only run their code on the first require. You should spend some personal time on learning how lua tables work, what is a reference to a lua table and understand how ModuleScripts work if you want to easily progress with your development.

Thank you for your response.
I actaully need this to return Enum.ProductPurchaseDecision.PurchaseGranted after data is saved or auto saved, not do do any modifications to data.

Is there any solution for that?

It’s been discussed about in this topic:

1 Like

I’m not sure if it has been mentioned in the past, and I would assume this is true, but when you “ForceLoad” a .Mock:LoadProfileAsync(), the ForceLoad does not override a normal :LoadProfileAsync().

Hi again,
how to handle “global values” like codes and some settings (basically all servers would get data from one key) without going over the limits?

Do it without ProfileService: GetAsync() the global settings key on a loop every 30 / 60’ish seconds on every server. If you need faster response you should use MessagingService.

1 Like

How can I disable saving the data?, it is a pain having to change the key everytime, I heard there is a mock version to solve this though

If you want to use this open source module and get help for it, you should at least read through the information that has already been prepared to answer the most basic questions:

https://madstudioroblox.github.io/ProfileService/api/#profilestoremock

2 Likes

Do I have to pass a ProfileTemplate? Isn’t the key enough to get the DataStore?(nvm doesn’t work). I’m trying out GlobalUpdates right now.

Edit: Will ProfileService include Leaderboard in the future? Like GetOrderedDataStore. That’d be pretty dang awesome.

Edit2: There’s Profile.Data, Profile.MetaData, and then Profile.GlobalUpdates, maybe a Profile.Leaderboard for exposing methods like saving into leaderboards or loading from it.

Hm, that would be extremely expensive and for no reason. You can easily create a leaderboard. And it woudn’t work anyway.

It wouldn’t be expensive unless it was ran. It would just be there if people needed it. Of course if it is expensive then it could be part of a different modulescript that acts as an extension to profileservice. Yes I could make it myself but I thought it’d be interesting if ProfileService had a function for get and setting leaderboards. It’s like a complete package of sort.

From your point of view there’s no reason to use it. However I have a reason to use it. Also you imply that you don’t support it but why is it that you say “you can easily create a leaderboard”? I’m talking about game leaderboards across servers not just inside servers. And why wouldn’t it work?

I read the Roblox wiki on it multiple times, I also looked through a ton of devforum posts. And I don’t think they ever said it wouldn’t work.

1 Like