Save your player data with ProfileService! (DataStore Module)

Thousands (or millions, for some games) of player data would be too large of a thing to load all at once. The closest thing to what you’re asking for was only released recently, but it’s purpose is still not for things like finding data of all players:

If you can list out the profile keys, then you can load actual profiles themselves via :LoadProfileAsync() by passing in the profile keys.

2 Likes

Same issue, but I would like to erase all data. Creating a new datastore does not solve the issue, because the old one would still be present - and take up memory.

How do you recommend someone access the player profiles across multiple scripts? Using _G? My data manager is in a module so if I wanted to access the profiles I would have to require the module in that script, should I put the profiles table in _G/shared?

It is best practice to make specific functions to edit data than it is having a public-read variable. However, if you really need it, then you can just define Profiles as a variable within the module like this:

module.Profiles = {}

My DataManager manages all data and will probably be very long, my thought process was that if I require this long module in another script just to use a simple table of profiles that it contains seemed very unnecessary because I would be requiring the whole module when I just needed to access the Profiles table.

Hi, currently running into an issue with ProfileService!

This is my code. In this case, player is Player_-1 and tier is equal to 1.

    print(Profiles)
    local profile = Profiles[player]
    profile.Data.SubTiers[tier] += 1
    print(Profiles)

When I print Profiles the first time, this is the data section that is outputted.
BUG1

When I print it the second time, the value has gone up as desired! The problem is, for some reason all other players in the game are also having the same value replicated, and I’m having a real headache working out why this is replicating, as I have made sure that this code is only being ran once and only for one profile.

BUG2

Any advice would be greatly appreciated :slight_smile:

4 Likes

A) You’ve set the same profile reference to multiple players
B) You’ve set the same member “SubTiers” table reference to multiple profiles - in this case you need to deepcopy before setting a template table to a new profile.

3 Likes

I completely forgot that tables are done by reference by default in lua… xD Thank you so much! This caused me such a headache.

Whenever I join, it kicks me because of ListenToRelease. This is happening every time. How do I fix this?

Hello, first I have to say I love this resource, it makes working with datastores so much simpler!

Question though, I was wondering how to properly erase the data of a specified profile. I’ve investigated ProfileStore:WipeProfileAsync(profileKey), but it only seems to work on already released profiles. Does clearing the Profile.Data table suffice (and then later calling Profile:Reconcile to fill it with the default values again), or should I be using a different method?

Yeah! :WipeProfileAsync() was made solely for GDPR compliance. To restart active profiles you can either grab them remotely with :LoadProfileAsync() or set them to an empty table and optionally reconcile on the server that currently owns the profile.

If you’re in the development testing phase, you could just change your ProfileStore name which will restart data for everyone.

2 Likes

Or use DataStore Editor from sleitnick - where you can edit,download and delete data. It costs robux but it is definitely worth buying.

1 Like

I wanted to add my own functions to each profile object without:

  1. Creating new functions for each profile object.
  2. Editing the main ProfileService module.

So I took the following approach:

local profile = profileStores.playerData:LoadProfileAsync("player_" .. plr.UserId)
	if (profile) then
		local mainTable = getmetatable(profile).__index
		setmetatable(
			profile,
			{
				__index = function(self, index)
					local exists1 = mainTable[index]
					if (exists1) then
						return exists1
					end
					return customPlayerProfile[index]
				end
			}
		)
		...

CustomPlayerProfile (module):

local customPlayerProfile = {}

function customPlayerProfile:TestLol()
	print("SUCCESS!", self.Data)
end

return customPlayerProfile

I want to ask, will this cause any errors or bugs in ProfileService and should I continue using this approach or try something else?

The code works though. I called profile:TestLol(). It worked and printed the data stored in the profile.

So I am working on a game a with a group that uses this module, I’ve only noticed how to use it during the last stages of development meaning it’s not going to be efficient for me to transfer all systems to this API.

I am slightly confused on how can I remove a user’s profile entirely from the API after I get all the values I need from it.

I have done process of transferring any data over to new datastore if the user has any existing data here but I am confused on how then I can delete the entire user profile.

How risky is using :OverwriteAsync()? I specifically need it to edit data if the player does not have any active session (is offline).

If you have to ask, then you probably need to use :LoadProfileAsync() instead.

1 Like

Why do I get this error everytime I leave?

ServerScriptService.ServerModules.DataManager.ProfileService:2411: attempt to call a nil value 

This is where the Profile:Release() function is

local function onPlayerRemoving(player)
	local playerProfile = Profiles[player]
	if playerProfile ~= nil then
		DataManager.ProfileRemoving:Fire(playerProfile, player)
		playerProfile:Release()
		print("[Data Manager]: Profile released")
	else
		warn("[Data Manager]: Profile already released!")
	end
end

I tried removing the ProfileRemoving:Fire() line but it still errors, is this a bug in the module?

I’m having trouble saving data from leaderstats. I don’t know how to transfer the value of the leaderstats (Like gems.Value) to Profile.Data.gems, please help!

I saw that we are NOT allowed to use mixed tables, BUT are we allowed to have different key types in different tables?

For instance:

local template = {
   Coins = 0,
   Wins = 0,
   Tools = {
      "Something",
      "Tool1",
      "another thing"
   },
   Settings = {
      Setting1 = false,
      Setting2 = true,
      Detail = "low"
   }
}

Are we allowed to use the example above?

Yes. Mixed key type limitations apply to individual tables only.

1 Like