Is there a recommended way to tell the client when their data changes?
Currently, I do something like this with AeroGameFramework
-- SERVER
local profile = self:Get(player)
if (profile) then
profile.Data.Cash += 50
end
-- Tell client their data changed
self:FireClient("DataUpdate", player, profile.Data)
-- CLIENT
local data = {}
DataService.DataUpdate:Connect(function(newData)
data = newData or {}
end)
Can you not require the module on client? cuz it gave me an error saying BindToClose can only be called on the server. Stack Begin Script 'ReplicatedStorage.DataManager.ProfileService', Line 242
This is probably one of the most unfair arguments I’ve seen going on in this thread. Bounding the data to the Player Instance doesn’t seem much a breaker, it’s what the entire module is dedicated for.
I’ve been using DataStore2 for a while and I’m debating whether it’s worth the transfer or not. People keep pointing out the 80 seconds hypothetical which I don’t think it terrible (at least because there’s nothing we can do about it).
I might test it out in a solo place for testing later on, but I remain unsure.
How would you make persistent servers or global leaderboards with DataStore2? I don’t want to use multiple systems to achieve variations of the same function.
There some problems I am facing where the ProfileService or my wrapper is yielding infinitely
wrapper-
local Rs = game:GetService("ReplicatedStorage");
local Players = game:GetService("Players");
local ProfileService = require(script:WaitForChild("ProfileService"));
local ProfileStore = ProfileService.GetProfileStore(
"Player",
{
Cash = 0
}
);
local Profiles = {};
local function MakeLeaderstats(player)
local profile = Profiles[player];
local leaderstats = Instance.new("Folder", player);
leaderstats.Name = "leaderstats";
local Cash = Instance.new("IntValue", leaderstats);
Cash.Name = "Cash"
Cash.Value = profile.Data.Cash
local thread = coroutine.wrap(function()
while true do
Cash.Value = profile.Data.Cash
game:GetService("RunService").Heartbeat:Wait();
end
end)
thread();
end
function OnPlayerAdded(player)
local profile = ProfileStore:LoadProfileAsync(
"Player_" .. player.UserId,
"ForceLoad"
);
profile:Reconcile();
if profile ~= nil then
profile:ListenToRelease(function()
Profiles[player] = nil;
player:Kick();
end)
if player:IsDescendantOf(Players) then
Profiles[player] = profile;
MakeLeaderstats(player);
else
profile:Release();
end
else
player:Kick();
end;
end;
for _,player in ipairs(Players:GetPlayers()) do
coroutine.wrap(OnPlayerAdded)(player)
end
Players.PlayerAdded:Connect(OnPlayerAdded);
Players.PlayerRemoving:Connect(function(player)
local profile = Profiles[player];
if profile ~= nil then
profile:Release();
Profiles[player] = nil;
player:Kick();
end
end)
local DataManager = {};
function DataManager:Get(player)
local profile = Profiles[player];
if profile then
return profile.Data;
end;
end;
return DataManager;
script which isn’t working
local ProfileService = require(game.ReplicatedStorage:WaitForChild("DataManager"));
game.Players.PlayerAdded:Connect(function(player)
print(player.Name) -- Doesn't fire
print(ProfileService:Get(player).Cash) --Doesn't fire
end)
local ProfileService
coroutine.wrap(function()
ProfileService = require(game.ReplicatedStorage:WaitForChild("DataManager"));
end)()
game.Players.PlayerAdded:Connect(function(player)
if not ProfileService then
repeat wait()
print("something") -- this prints infinitely
until ProfileService
end
print(player.Name) -- Doesn't fire
print(ProfileService:Get(player).Cash) --Doesn't fire
end)
Refer to the official example (top post) - towards the bottom there’s a for loop that iterates over existing players before .PlayerAdded connection is made.
On a different note, your code that “waits for ProfileService” is loading your wrapper module (line 4, WaitForChild name parameter) - these are errors on your own end.
Just a few questions as I’m rather new with using this module. With clans/factions having no session locking (not releasing the profile, not listening to release, and having different servers load the profile) could it be setup like this?
local module = {}
local ProfileService = require(script.ProfileService)
local ClanProfileStore = ProfileService.GetProfileStore("ClanSaveData",{})
local ClanProfile = ClanProfileStore:LoadProfileAsync("Clan","ForceLoad")
function module.ReturnClanProfile()
return ClanProfile
end
return module
--planning to add more functions, which is why I'm not just returning clanprofile
I’m planning to add real time cross server updates to these clans. Would using messaging service and informing all servers of new changes and then having those servers save that data be the most effective/efficient way to provide real time updates?
For example, in server A someone does something that makes their clan score go up by 3, another member of that same clan is in another server, server B, now server A would send a message to all running servers to update their clan score. This way any changes server B makes reflects the true amount of clan score they have (and of course server B would be doing the same for any changes it makes).
ProfileService is designed for profiles that are acessed by one server at a time - this will not work.
Yeah, you can use ProfileService for anything other than players as long as the individual profiles are used on one server at a time - otherwise you’ll need to make custom code with update listeners and messagingservice.
I’ve been wanting to experiment with ProfileService and took the time to do so today after looking at @EncodedLua’s tutorial.
Is there any reason why I should be getting the following warning:
The code is nearly identical to the script provided in the tutorial (except a few variable name changes.) Did I miss a step in the tutorial? Code can be provided if it helps solve this issue.
From the info and personal experience I’ve gathered, such warnings are not dangerous at all as long as you don’t get like a ridiculous amount of them at a time (like 10 every second). I tried to avoid such warnings while coding ProfileService as much as possible, but there are cases where it’s necessary to put a request on queue immediately.
Thank you, I feel like an idiot for missing this portion of the documentation.
I’ve also stumbled upon the script not working in Studio (works just fine in a regular game session), is this just something I’ll have to get used to in regards to testing?
Not sure if this was answered but if you update the ProfileTemplate, will old players be able to get that data saved, or are there special steps needed to be taken for that to be possible?
You can use the Reconcile() method on a Profile, this will compare the existing profile data structure with the data template being used and will fill in missing values.