diff --git a/docs/tutorial/basic_usage.md b/docs/tutorial/basic_usage.md index 9b19dcf..6801637 100644 --- a/docs/tutorial/basic_usage.md +++ b/docs/tutorial/basic_usage.md @@ -8,90 +8,85 @@ The code below is a basic profile loader implementation for ProfileService: handled by using `Profile:ListenToRelease(listener_function)` - any amount of functions can be added! ``` lua --- ProfileTemplate table is what empty profiles will default to. --- Updating the template will not include missing template values --- in existing player profiles! -local ProfileTemplate = { - Cash = 0, - Items = {}, - LogInTimes = 0, -} - ------ Loaded Modules ----- - -local ProfileService = require(game.ServerScriptService.ProfileService) - ------ Private Variables ----- - +local ServerScriptService = game:GetService("ServerScriptService") local Players = game:GetService("Players") -local ProfileStore = ProfileService.GetProfileStore( - "PlayerData", - ProfileTemplate -) - -local Profiles = {} -- [player] = profile +local ProfileService = require(ServerScriptService.ProfileService) ------ Private Functions ----- +-- Use the profile service to create the profile store. The second argument is the template. +-- The template table is what empty profiles will default to. Since loadProfile reconciles the profile, +-- missing values will be filled in from the template in existing profiles. +local profileStore = ProfileService.GetProfileStore("PlayerData", { + Cash = 0, + Items = {}, + LogInTimes = 0, +}) -local function GiveCash(profile, amount) - -- If "Cash" was not defined in the ProfileTemplate at game launch, - -- you will have to perform the following: - if profile.Data.Cash == nil then - profile.Data.Cash = 0 - end - -- Increment the "Cash" value: - profile.Data.Cash = profile.Data.Cash + amount -end +-- The profiles table relates active players to their profiles. +local profiles = {} -local function DoSomethingWithALoadedProfile(player, profile) +local function onProfileLoaded(player, profile) profile.Data.LogInTimes = profile.Data.LogInTimes + 1 - print(player.Name .. " has logged in " .. tostring(profile.Data.LogInTimes) - .. " time" .. ((profile.Data.LogInTimes > 1) and "s" or "")) - GiveCash(profile, 100) + print(string.format("%s has logged in %i times.", player.Name, profile.Data.LogInTimes)) + + profile.Data.Cash = profile.Data.Cash + 100 print(player.Name .. " owns " .. tostring(profile.Data.Cash) .. " now!") end -local function PlayerAdded(player) - local profile = ProfileStore:LoadProfileAsync("Player_" .. player.UserId) - if profile ~= nil then - profile:AddUserId(player.UserId) -- GDPR compliance - profile:Reconcile() -- Fill in missing variables from ProfileTemplate (optional) - profile:ListenToRelease(function() - Profiles[player] = nil - -- The profile could've been loaded on another Roblox server: - player:Kick() - end) - if player:IsDescendantOf(Players) == true then - Profiles[player] = profile - -- A profile has been successfully loaded: - DoSomethingWithALoadedProfile(player, profile) - else - -- Player left before the profile loaded: - profile:Release() - end - else +local function loadProfile(player) + local profile = profileStore:LoadProfileAsync("Player_" .. player.UserId) + if not profile then -- The profile couldn't be loaded possibly due to other - -- Roblox servers trying to load this profile at the same time: + -- Roblox servers trying to load this profile at the same time: player:Kick() + return + end + + -- GDPR compliance + profile:AddUserId(player.UserId) + + -- Fill in missing variables from ProfileTemplate + profile:Reconcile() + + -- If the player is still around even after their profile has been released, + -- then we should kick them. The profile could've been loaded on another Roblox server. + profile:ListenToRelease(function() + player:Kick() + end) + + if player:IsDescendantOf(Players) == true then + -- A profile has been successfully loaded: + return profile + else + -- Player left before the profile loaded: + profile:Release() end end ------ Initialize ----- +-- Adds a profile to the profiles table. +local function addProfile(player) + -- Load the profile + local profile = loadProfile(player) + -- Save it into the profiles table + profiles[player] = profile + -- Give the player their cash and increment their log in times + onProfileLoaded(player, profile) +end --- In case Players have joined the server earlier than this script ran: +-- Add the profiles of the players who have already joined the server for _, player in ipairs(Players:GetPlayers()) do - task.spawn(PlayerAdded, player) + task.spawn(addProfile, player) -- Loading a profile is async end ------ Connections ----- - -Players.PlayerAdded:Connect(PlayerAdded) +-- Add the profiles of new players +Players.PlayerAdded:Connect(addProfile) +-- When a player leaves the game, release the profile and remove it from the profiles table Players.PlayerRemoving:Connect(function(player) - local profile = Profiles[player] - if profile ~= nil then + local profile = profiles[player] + if profile then profile:Release() + profile[player] = nil end end) ```