Hello Developers,
Happy Friday! So I was watching a tutorial on Youtube about Profile Service + Data Replication. I was following along and writing the code exactly how the person in the video does it, however my code is not working.
the reason it isn’t working is because everytime I print a player’s data it’s printing nil, but I don’t know why. Can anyone help?
Init Script (ServerScriptService):
local ServerStorage = game:GetService("ServerStorage")
local SystemsFolder = ServerStorage:WaitForChild("Systems")
local DataService = require(SystemsFolder:WaitForChild("DataService"))
DataService:Init()
TestScript Script (ServerScriptService):
local DataService = require(game:GetService("ServerStorage"):WaitForChild("Systems"):WaitForChild("DataService"))
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GetDataRemoteFunction = ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("GetData")
GetDataRemoteFunction.OnServerInvoke = function(Player, value )
local profile = DataService:GetPlayerProfile(Player, false)
if profile then
return profile.Data
end
return nil
end
DataService Module (ServerStorage>Systems):
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ServerModules = ServerStorage:WaitForChild("Modules")
local ProfileService = require(ServerModules:WaitForChild("ProfileService"))
local ProfileTemplate = {
-- game values
Cash = 0,
Gems = 0,
-- analytic
LogInTimes = 0,
TotalGameTime = 0,
}
local GameProfileStore = ProfileService.GetProfileStore("PlayerData1", ProfileTemplate)
local Profiles = {}
local JoinTimes = {}
local function FloorNumber(number, decimalPlaces)
decimalPlaces = decimalPlaces or 2 -- this is saying that if decimalPlaces is not given, just make it "2"
return math.floor(number * math.pow(10, decimalPlaces)) / math.pow(10, decimalPlaces)
end
local function OnPostProfileLoad(player, profile)
profile.Data.LogInTimes += 1
local totalLogins = profile.Data.LogInTimes
print( string.format('%s has logged in %s time%s', player.Name, totalLogins, (totalLogins > 1) and 's' or '') )
print( ' This player has played a total of ' ..profile.Data.TotalGameTime..' seconds before joining this server.' )
-- ^ ^ ^------------------------.
-- player time here specific login number here time or time(s) depending on the number of login times
-- ex)
-- SPOOK_EXE has logged in 1 time.
-- SPOOK_EXE has logged in 2 times.
JoinTimes[player] = tick()
end
local function PlayerAdded(player)
local profile = GameProfileStore:LoadProfileAsync(tostring(player.UserId))
if profile then
profile:AddUserId(player.UserId) -- GDPR compliance
profile:Reconcile() -- putting all missing template values into the active data ( optional )
profile:ListenToRelease(function()
Profiles[player] = nil
-- The profile could've been loaded on another Roblox server:
player:Kick('Profile has been loaded onto another Server.')
end)
if player:IsDescendantOf(Players) then
OnPostProfileLoad(player, profile)
Profiles[player] = profile
else
-- Player left before the profile loaded:
profile:Release()
end
else
player:Kick('Failed to Load Data : OnPlayerAdded_1')
end
end
--Lets say you have a Admin Panel and you try to edit the player's data, it will kick them from the server
-- // Module // --
local Module = {}
function Module:GetPlayerProfile(Player, Yield)
local profile = Profiles[Player]
if Yield and not profile then
repeat task.wait(0.1)
profile = Profiles[Player]
until profile or (not Player.Parent)
end
end
function Module:Init()
for _, player in ipairs(Players:GetPlayers()) do
coroutine.wrap(PlayerAdded)(player)
end
Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(function(player)
local profile = Profiles[player]
if profile ~= nil then
--add the duration they've played to the data
local duration = tick() - JoinTimes[player]
profile.Data.TotalGameTime += duration
profile.Data.TotalGameTime = FloorNumber(profile.Data.TotalGameTime, 3)
print( string.format('%s has played a total of %s seconds this session, totalling the total to %s seconds', player.Name, FloorNumber(duration), profile.Data.TotalGameTime))
JoinTimes[player] = nil
--release the profile so other games can load it
profile:Release()
end
end)
end
return Module
GetData Local Script (StarterPlayer>StarterPlayerScripts):
local HTTPService = game:GetService("HttpService")
local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GetDataRemoteFunction = ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("GetData")
local Interface = LocalPlayer.PlayerGui:WaitForChild('Interface')
local activeData = nil
coroutine.wrap(function()
while task.wait(1) do
activeData = GetDataRemoteFunction:InvokeServer()
print(activeData)
Interface.Label.Text = "Data: ".. (activeData and HTTPService:JSONEncode(activeData) or "No Data")
end
end)()
Additionall, here’s the place file:
ProfileService Data Service game.rbxl (67.7 KB)
Also, here’s the video that I was watching this off of: https://www.youtube.com/channel/UCEwgh-qSICxQ0dHpwBOCXIg
Video of my problem: