How to make function to get player data using profile service?

Module:

local Services = require(game.ReplicatedStorage.Utils.Services).new():GetServices()

local PlayerDataHandler = {}

local dataTemplate = {
	Coins = 100,
	Rebirths = 0,
	Level = 1,
	Exp = 0,
	Need = 100,
	Rasa = "Human",
	Location = "Spawn",
}

local ProfileService = require(Services.ServerScriptService.Libs.ProfileService)

local ProfileStore = ProfileService.GetProfileStore(
	"PlayerProfile",
	dataTemplate
)

local Profiles = {}

local function PlayerAdded(player)
	local profile = ProfileStore:LoadProfileAsync("Player"..player.UserId)
	
	if profile then
		profile:AddUserId(player.UserId)
		profile:Reconcile()
		
		profile:ListenToRelease(function()
			Profiles[player] = nil
			
			player:Kick()
		end)
		
		if not player:IsDescendantOf(Services.Players) then
			profile:Release()
		else
			Profiles[player] = profile
			
			print(Profiles[player].Data)
		end
	else
		player:Kick()
	end
end

function PlayerDataHandler:Init()
	for _, player in Services.Players:GetPlayers() do
		task.spawn(PlayerAdded, player)
	end
	
	Services.Players.PlayerAdded:Connect(PlayerAdded)
	
	Services.Players.PlayerRemoving:Connect(function(player)
		if Profiles[player] then
			Profiles[player]:Release()
		end
	end)
end

local function GetProfile(player)
	assert(Profiles[player], string.format("Profile does not exist for %s", player.UserId))
	
	return Profiles[player]
end

function PlayerDataHandler:Get(player, key)
	local profile = GetProfile(player)
	assert(profile.Data[key], string.format("Data does not exist for key %s", key))
	
	return profile.Data[key]
end

function PlayerDataHandler:Set(player, key, value)
	local profile = GetProfile(player)
	assert(profile.Data[key], string.format("Data does not exist for key %s", key))
	
	assert(type(profile.Data[key]) == type(value))
	
	profile.Data[key] = value
end

function PlayerDataHandler:Update(player, key, callback)
	local profile = GetProfile(player)
	
	local oldData = self:Get(player, key)
	local newData = callback(oldData)
	
	self:Set(player, key, newData)
end

return PlayerDataHandler

Script:

local Services = require(game.ReplicatedStorage.Utils.Services).new():GetServices()

local PlayerDataHandler = require(Services.ServerScriptService.PlayerData:WaitForChild("PlayerDataHandler"))

PlayerDataHandler:Init()

Function: (dont work)

RemoteFunctions.GetData.OnServerInvoke = function(player: Player)
	local data = -- Function to load

	return data
end

1 Like

You set the profiles as a local table inside of your ProfileHandler module. This means you can’t access the profile table from any other script. This is as easy as attaching the profiles table to the module so that you can access it from any other script, or just have an entirely different module that handles all the profiles which is what I prefer.

First method:

PlayerDataHandler.Profiles = {} -- Allowing the table to be viewed from other scripts

Second method:

local ProfileManager = {}

ProfileManager.Profiles = {} -- same thing but separate module

return ProfileManager
3 Likes

where to insert these lines or what to replace them with?

Where you had this at the beginning of your code:

Replace the Profiles = {} with either of the methods I mentioned earlier that indexes the module

now how do I create a function to get the data?

All you now have to do is just index it from its original location

local Data = ProfileManager.Profiles[player].Data -- I index with data since that's where the player data is stored

As a personal preference, I usually only index the player data with one module so that so I could just request that data from anywhere else.

I did something similar but it doesn’t work

RemoteFunctions.GetData.OnServerInvoke = function(player: Player)
	local Profiles = PlayerDataHandler.Profiles[player]
	
	local profile = Profiles.Data
	if not profile then return end
	
	print(profile)

	return profile
end
local data = RemoteFunctions.GetData:InvokeServer(Player)

error: ServerScriptService.Remotes:13: attempt to index nil with ‘Data’

You may want to make this edit if you haven’t already, because this might be the issue of why you’re receiving

[quote=“NotAngel, post:1, topic:3109953, username:Dozetopgg”]

Change that last line to:

else
	PlayerDataHandler.Profiles[player] = profile

she’s already changed the error remains

Can you share the full script because I feel like I’m missing info here.

local Services = require(game.ReplicatedStorage.Utils.Services).new():GetServices()

local PlayerDataHandler = {}

local dataTemplate = {
	Coins = 100,
	Rebirths = 0,
	Level = 1,
	Exp = 0,
	Need = 100,
	Rasa = "Human",
	Location = "Spawn",
}

local ProfileService = require(Services.ServerScriptService.Libs.ProfileService)

local ProfileStore = ProfileService.GetProfileStore(
	"PlayerProfile",
	dataTemplate
)

PlayerDataHandler.Profiles = {}

local function PlayerAdded(player: Player)
	local profile = ProfileStore:LoadProfileAsync("Player"..player.UserId)
	
	if profile then
		profile:AddUserId(player.UserId)
		profile:Reconcile()
		
		profile:ListenToRelease(function()
			PlayerDataHandler.Profiles[player] = nil
			
			player:Kick()
		end)
		
		if not player:IsDescendantOf(Services.Players) then
			profile:Release()
		else
			PlayerDataHandler.Profiles[player] = profile
			
			print(profile.Data)
		end
	else
		player:Kick()
	end
end

function PlayerDataHandler:Init()
	for _, player in Services.Players:GetPlayers() do
		task.spawn(PlayerAdded, player)
	end
	
	Services.Players.PlayerAdded:Connect(PlayerAdded)
	
	Services.Players.PlayerRemoving:Connect(function(player: Player)
		if PlayerDataHandler.Profiles[player] then
			PlayerDataHandler.Profiles[player]:Release()
		end
	end)
end

local function GetProfile(player: Player)
	assert(PlayerDataHandler.Profiles[player], string.format("Profile does not exist for %s", player.UserId))
	
	return PlayerDataHandler.Profiles[player]
end

function PlayerDataHandler:Get(player: Player, key: string)
	local profile = GetProfile(player)
	assert(profile.Data[key], string.format("Data does not exist for key %s", key))
	
	return profile.Data[key]
end

function PlayerDataHandler:Set(player: Player, key: string, value: number)
	local profile = GetProfile(player)
	assert(profile.Data[key], string.format("Data does not exist for key %s", key))
	
	assert(type(profile.Data[key]) == type(value))
	
	profile.Data[key] = value
end

function PlayerDataHandler:Update(player: Player, key: string, callback: (any) -> any)
	local profile = GetProfile(player)
	
	local oldData = self:Get(player, key)
	local newData = callback(oldData)
	
	self:Set(player, key, newData)
end

return PlayerDataHandler
RemoteFunctions.GetData.OnServerInvoke = function(player: Player)
	local Profiles = PlayerDataHandler.Profiles[player]
	
	print(Profiles)
	
	local profile = Profiles.Data
	if not profile then return end
	
	print(profile)

	return profile
end
local data = RemoteFunctions.GetData:InvokeServer(Player)

Ok so I tried this in my own studio and I kept erroring. I realized that I forgot to initialize. Did you initialize your module?

my initialization:

local Services = require(game.ReplicatedStorage.Utils.Services).new():GetServices()

local PlayerDataHandler = require(Services.ServerScriptService.PlayerData:WaitForChild("PlayerDataHandler"))

PlayerDataHandler:Init()

That’s very odd because I used the same scripts and it worked, let me try to find any other changes that I made.

Can you do print checks on your services util to see if they are properly returning because that’s the only thing that was the only other change I made on my end.

--[[ {
                    ["Coins"] = 100,
                    ["Exp"] = 0,
                    ["Level"] = 1,
                    ["Location"] = "Spawn",
                    ["Need"] = 100,
                    ["Rasa"] = "Human",
                    ["Rebirths"] = 0
                 }  -  Server - Script:13
  18:28:43.747   ▼  {
                    ["Coins"] = 100,
                    ["Exp"] = 0,
                    ["Level"] = 1,
                    ["Location"] = "Spawn",
                    ["Need"] = 100,
                    ["Rasa"] = "Human",
                    ["Rebirths"] = 0
                 }  -  Client - LocalScript:2
--]]

That is my output which means everything worked correctly

if I do this then nil disappears

local Profiles = PlayerDataHandler.Profiles

{} - Server - Remotes:13

Do you get all the data on the client?

no I get an empty table {} on the client

oh, I get the table on the server, but on the client nil

What is your code for the OnServerInvoke?