Any Problems With My Data Manager Using Profile Service?

Hi everyone! I’m new to using ProfileService and would like to know if I am using it correctly and efficiently. I have watched and read through multiple tutorials and read through the API. The DataStore Module is below and so are some questions I have.

My DataStore Module
--//Game Services\\--

local Players = game:GetService('Players')

--//Modules\\--

local ProfileService = require(game.ServerScriptService.Modules.ProfileService)

--//Profile Stuff\\--

local ProfileTemplate = {
	TestValue = 0,
	TestTable = {},
	TestString = 'Test',
}

local TestDataStore = ProfileService.GetProfileStore("TestDataStore", ProfileTemplate) --//Get DataStore

local Profiles = {} --//Profile Table

--//PlayerDataManager\\--

local PlayerDataManager = {}

--//Global Functions\\--

function PlayerDataManager:AddValue(player, Value)
	
	local Profile = Profiles[player] --//Get Player Profile.
	
	if Profile then --//Profile Exists Then...
		if typeof(Value) == 'number' then --//Check If Value Is Number.
			Profile.Data.TestValue += Value --//Add Value.
			print(Profile.Data.TestValue)
		end
	else
		warn('Cannot Get Data From '..player.Name..'!!!') --//Warn Cannot Get Data From Player
	end
end

--//Player Functions\\--

local function PlayerAdded(player)
	
	local Profile = TestDataStore:LoadProfileAsync('Player_'..player.UserId) --//Load Player Profile.
	if Profile ~= nil then
		Profile:AddUserId(player.UserId)
		Profile:Reconcile() --//Fill In Missing Variables.
		Profile:ListenToRelease(function()
			Profiles[player] = nil
			--//If Loaded On Another Server, Kick Player.
			player:Kick('Couldnt Load Your Data! Please Rejoin.')
		end)
		if player:IsDescendantOf(Players) == true then
			Profiles[player] = Profile
			--//Profile Was Loaded.
			print(Profile.Data)
		else
			--//If Player Left Before Profile Was Loaded, Release Profile.
			Profile:Release()
		end
	else
		--//If Other Servers Try To Load Profile At Same Time, Kick.
		player:Kick('Couldnt Load Your Data! Please Rejoin.') 
	end
end

local function PlayerRemoving(player)
	
	local Profile = Profiles[player] --//Get Player Profile
	
	if Profile ~= nil then --//If Profile Exists, Release It.
		Profile:Release()
	end
end

--//If Players Join Before Script Loads\\--

for _, player in ipairs(Players:GetPlayers()) do
	task.spawn(PlayerAdded, player)
end

--//Player Connections\\--

Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)
game:BindToClose(function()
	for i, player in pairs(Players:GetChildren()) do
		PlayerRemoving(player)
	end
end)

return PlayerDataManager
  1. Is is necessary to use :AddUserID()?

  2. In the :AddValue() function I made, should I take more action then just a warn if the script cannot get data from the player?

  3. Is there anything more I should be adding to my PlayerAdded() and PlayerRemoving() functions?

  4. Do I really need to loop through the players in case the script had not loaded in yet?

Part I'm Referring To
for _, player in ipairs(Players:GetPlayers()) do
	task.spawn(PlayerAdded, player)
end
  1. Do I need a BindToClose(function() when using ProfileService?

Thank you for the help in advance :grinning:.

Also, is there anything I should add? I’m trying to make this pretty much 100% accurate.

Hello there. I have recently started using ProfileService, so I can only answer some of your questions. Please correct me if my answers are wrong.

  1. Is it necessary to use :AddUserID() ?

Yes, as far as I am aware. According to the API, :AddUserId is not only used to associate multiple users in a single profile but it is also used to comply with GDPR (the right to be erased).

“GDPR stands for the General Data Protection Regulation. The GDPR is a law in the European Union that focuses on protecting the personal information of everyone in the European Union and European Economic Area by guaranteeing specific rights to the collection, use, and sharing of their personal information. These rights extend beyond the territorial boundaries of Europe, such that many companies or individuals that collect EU personal information are subject to GDPR.”

You can read more about it here.

  1. Do I really need to loop through the players in case the script had not loaded in yet?

In case a player joined the server before your data manager script started running, yes.

  1. Do I need a BindToClose(function() when using ProfileService?

No, ProfileService automatically saves all the data for you, even when the server is closing.

2 Likes

Thank you for your response and for bringing GDPR to my attention! My only other question for you is if I call AddValue and it can’t get the player data, should I do anything more than just warn, Ex. Kick the player.

In my opinion, it would be ideal to create something that will secure and absolutely guarantee that each player’s profile has been loaded or cached. But suppose your data manager is unable to locate the player’s profile. In that case, why would you let the player continue playing on the same server if you are unable to change or retrieve the player’s profile? This would be a problem because if somebody attempted to make a purchase in your game and you needed to change their profile, how would you do that if your data manager couldn’t locate their profile? Therefore, I would say that you should kick the player. However, it would be much preferable to create something that would ensure that the player’s profile is loaded on the same server.

1 Like

You know what I just realized that there already is something that guarantees the player’s data will load and if not kick them in the playeradded function! Thank you for the response.

1 Like