ProfileStore Wrapper

This will handle all player joins and leaving for you.

Note: you will have to do your own player joining stuff to do leaderstats, etc.

Example:

--> Setting up a profile store
local PlayerData = require(script.PlayerData)
local DataTemplate = {
	Coins = 0,
	Inventory = {
		Sword = {
			Quantity = 0,
		}
	}
}

local ProfileStore = PlayerData.new('Example_Store', DataTemplate)

--> Getting a players profile
local Player = game:GetService('Players'):GetPlayers()[1]
local Profile = ProfileStore:GetProfile(Player)

print(`{Player.Name}s profile:`)
print(Profile)

--> Getting a users profile by profile key
local Profile = ProfileStore:GetAsync('1') --> roblox's profile store
print(`ROBLOXs profile:`)
print(Profile)

--> Messaging async
local result = ProfileStore:MessageAsync('1', {Coins = 5})
print('Successful message: ', result)

--> Version Query
local VersionQuery = ProfileStore:VersionQuery('1', Enum.SortDirection.Ascending, DateTime.fromLocalTime(2024, 6, 24, 1, 0, 0, 0))
print(VersionQuery:NextAsync())

Model:

1 Like

Update:
Added 2 methods to wait for a profile.
Added this because I noticed if you try to get their profile right when they join, it doesn’t register it.

Example:

--!strict
local ReplicatedStorage = game:GetService('ReplicatedStorage')

--> util
local util = require(ReplicatedStorage.Utility)
local PlayerUtil = util.PlayerUtil

--> refs
local ProfileStores = require(script.Parent.ProfileStores)
local PlayerData = ProfileStores.PlayerData

--> Method 1
PlayerUtil.PlayerAdded(function(player : Player)
	local profile = PlayerData:WaitForProfile(player)
	
	local leaderstats = Instance.new('Folder')
	local Streak = Instance.new('NumberValue')
	local Level = Instance.new('NumberValue')

	leaderstats.Name = 'leaderstats'
	Streak.Name = 'Streak'
	Level.Name = 'Level'

	Streak.Parent = leaderstats
	Level.Parent = leaderstats
	leaderstats.Parent = player

	Streak.Value = profile.Data.Stats.Streak
	Level.Value = profile.Data.Level
end)

--> Method 2
PlayerData.ProfileLoaded:Connect(function(player : Player, profile)
	local leaderstats = Instance.new('Folder')
	local Streak = Instance.new('NumberValue')
	local Level = Instance.new('NumberValue')

	leaderstats.Name = 'leaderstats'
	Streak.Name = 'Streak'
	Level.Name = 'Level'

	Streak.Parent = leaderstats
	Level.Parent = leaderstats
	leaderstats.Parent = player

	Streak.Value = profile.Data.Stats.Streak
	Level.Value = profile.Data.Level
end)

return nil

Update:
Added profile mocking for studio.
Added leaderstats.

Example:

--> Mocking:
PlayerData.new('Test_Data_0', {}, false)  --> Will not save in studio
PlayerData.new('Test_Data_1', {})         --> Will not save in studio
PlayerData.new('Test_Data_2', {}, true)   --> Will save in studio

--> leaderstats
local Profiles = PlayerData.new('Test_Store_0', {
	Stats = {
		Level = 1,
		Streak = 0,
	},
	
	Coins = 500
}, false, {
	['Level'] = 'Stats/Level', --> Name = Path in data table.
	['Streak'] = 'Stats/Streak'
})

Profiles:UpdateLeaderstats(player) --> will update the leaderstats with the updated profile values.