Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Example: ProfileStore Integration

Integrating ReplicatedRegistry2 with ProfileService for persistent player data.

Server Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Players = game:GetService("Players")

local ProfileService = require(ServerScriptService.ProfileService)
local ReplicatedRegistry = require(ReplicatedStorage.ReplicatedRegistry2)
local server = ReplicatedRegistry.server

-- Setup remotes
ReplicatedRegistry.server.set_remote_instances(
    ReplicatedStorage.RequestFullRemote,
    ReplicatedStorage.SendChangesRemote
)

-- ProfileStore setup
local ProfileStore = ProfileService.GetProfileStore(
    "PlayerData",
    {
        coins = 0,
        level = 1,
        inventory = {},
        stats = {
            kills = 0,
            deaths = 0,
            playtime = 0
        }
    }
)

local Profiles = {}

-- Filter for player profiles
local profileFilter = ReplicatedRegistry.get_filter({
    rate_limit = 10,
    custom = function(sender, register_key, tbl, changes)
        -- Ensure player only modifies their own profile
        return register_key == sender.UserId
    end
})

Players.PlayerAdded:Connect(function(player)
    local profile = ProfileStore:LoadProfileAsync(`Player_{player.UserId}`)
    
    if not profile then
        player:Kick("Failed to load data")
        return
    end
    
    profile:AddUserId(player.UserId)
    profile:Reconcile()
    
    profile:ListenToRelease(function()
        Profiles[player] = nil
        server.deregister(player.UserId)
        player:Kick("Profile released")
    end)
    
    if not player:IsDescendantOf(Players) then
        profile:Release()
        return
    end
    
    Profiles[player] = profile
    
    -- Register profile data with ReplicatedRegistry
    local key = player.UserId
    server.register(key, profile.Data, profileFilter)
    
    -- Listen for changes from client
    ReplicatedRegistry.on_recieve(key, function(sender, tbl, changes)
        print(`{sender.Name} updated profile:`)
        for _, change in changes do
            print(`  {table.concat(change.p, ".")} = {change.v}`)
        end
    end)
    
    -- Periodic sync to client (every 10 seconds)
    task.spawn(function()
        while Profiles[player] do
            task.wait(10)
            if Profiles[player] then
                server.to_clients(key, {player})
            end
        end
    end)
end)

Players.PlayerRemoving:Connect(function(player)
    local profile = Profiles[player]
    if profile then
        profile:Release()
        Profiles[player] = nil
        server.deregister(player.UserId)
    end
end)

-- Example: Give rewards
function giveReward(player, coins, xp)
    local profile = Profiles[player]
    if not profile then return end
    
    local proxy = ReplicatedRegistry.server.view_as_proxy(player.UserId)
    
    proxy.incr({"coins"}, coins)
    proxy.incr({"level"}, xp)
    
    -- Replicate to player
    proxy.replicate({player})
end

-- Example: Add item to inventory
function giveItem(player, itemName)
    local profile = Profiles[player]
    if not profile then return end
    
    local data = ReplicatedRegistry.server.view(player.UserId)
    data.inventory[itemName] = true
    
    ReplicatedRegistry.server.to_clients(player.UserId, {player})
end

-- Example: Update stats
function recordKill(player)
    local profile = Profiles[player]
    if not profile then return end
    
    local proxy = ReplicatedRegistry.server.view_as_proxy(player.UserId)
    proxy.incr({"stats", "kills"}, 1)
    proxy.replicate({player})
end

Client Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local ReplicatedRegistry = require(ReplicatedStorage.ReplicatedRegistry2)

-- Setup remotes
ReplicatedRegistry.client.set_remote_instances(
    ReplicatedStorage.RequestFullRemote,
    ReplicatedStorage.SendChangesRemote
)

local player = Players.LocalPlayer
local key = player.UserId

-- Wait for data to be ready
local playerData = ReplicatedRegistry.client.view(key)

-- Listen for profile updates
ReplicatedRegistry.on_recieve(key, function(sender, tbl, changes)
    for _, change in changes do
        local path = table.concat(change.p, ".")
        print(`Profile updated: {path} = {change.v}`)
        
        -- Update UI based on what changed
        if change.p[1] == "coins" then
            updateCoinsUI(tbl.coins)
        elseif change.p[1] == "level" then
            updateLevelUI(tbl.level)
        elseif change.p[1] == "stats" then
            updateStatsUI(tbl.stats)
        end
    end
end)

-- Initial UI setup
updateCoinsUI(playerData.coins)
updateLevelUI(playerData.level)
updateStatsUI(playerData.stats)

-- Example: Purchase system
function tryPurchase(itemName, cost)
    local data = ReplicatedRegistry.client.view(key)
    
    if data.coins >= cost then
        -- Optimistic update
        data.coins -= cost
        data.inventory[itemName] = true
        
        -- Server will validate
        ReplicatedRegistry.client.to_server(key)
        return true
    end
    
    return false
end

Notes

  • ProfileStore handles persistence
  • ReplicatedRegistry handles real-time sync
  • Server validates all client changes
  • Client gets immediate feedback with optimistic updates
  • Profile data automatically reconciles on load