### Control Replication with ReplicateFor and DestroyFor Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Dynamically manage which clients receive replica data. Use ReplicateFor to start replication to specific players or 'All', and DestroyFor to stop it. This is useful for managing large worlds or player-specific data. ```lua local ReplicaService = require(game:GetService("ServerScriptService").ReplicaService) local Players = game:GetService("Players") local ChunkToken = ReplicaService.NewClassToken("WorldChunk") -- Create chunk replica without initial replication local chunkReplica = ReplicaService.NewReplica({ ClassToken = ChunkToken, Tags = {ChunkX = 5, ChunkY = 10}, Data = { Entities = {}, Terrain = {}, }, -- No Replication = starts unreplicated }) -- Player enters chunk area - start replicating to them local function onPlayerEnterChunk(player) chunkReplica:ReplicateFor(player) print("Chunk replicated to", player.Name) end -- Player leaves chunk area - stop replicating local function onPlayerLeaveChunk(player) chunkReplica:DestroyFor(player) print("Chunk destroyed for", player.Name) end -- Or replicate to everyone at once local function makeChunkPublic() chunkReplica:ReplicateFor("All") end -- Stop replicating to everyone (must call before selective destroy) local function makeChunkPrivate() chunkReplica:DestroyFor("All") end ``` -------------------------------- ### WriteLib.lua ModuleScript Example Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md This ModuleScript defines a dictionary of mutator functions. These functions are intended to be used with Replica:Write() to modify replica data synchronously across server and clients. Ensure this script is a descendant of a replicated instance. ```lua local WriteLib = { -- Mutator functions will receive the first parameter as the -- Replica being mutated; Custom parameters passed with -- Replica:Write() will follow RestockAll = function(replica, restock_count, max_count) for soda_name, old_count in pairs(replica.Data.Cans) do -- Using mutators inside WriteLibs will trigger client-side -- listeners as expected: replica:SetValue( {"Cans", soda_name}, math.min(old_count + restock_count, max_count) ) end end, TakeCan = function(replica, soda_name, amount) --> amount_taken local old_count = replica.Data.Cans[soda_name] or 0 local amount_taken = math.min(old_count, amount) if amount_taken > 0 then replica:SetValue({"Cans", soda_name}, old_count - amount_taken) end return amount_taken end, AddCoins = function(replica, coin_count) replica:SetValue({"CoinsInside"}, replica.Data.CoinsInside + coin_count) end, TakeAllCoins = function() --> coins_taken local coins = replica.Data.CoinsInside replica:SetValue({"CoinsInside"}, 0) replica:Write("RestockAll", 1, 10) -- WriteLibs can use their own mutators! return coins end, -- A note for power users: -- replica.Children and replica.Parent can be accessed within -- WriteLib mutator functions - built-in and custom mutators -- can be triggered for those replicas as well. Go wild! } return WriteLib ``` -------------------------------- ### Replica:ListenToChange() Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Creates a listener which gets triggered by Replica:SetValue() calls. ```APIDOC ## Replica:ListenToChange() ### Description Creates a listener which gets triggered by Replica:SetValue() calls. ### Parameters #### Request Body - **path** (table) - Required - The path to the value. - **listener** (function) - Required - Callback function receiving (new_value, old_value). ``` -------------------------------- ### Get Replica by ID Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Use ReplicaController.GetReplicaById() to retrieve a client-side replica that has a matching Replica.Id. Returns nil if no such replica is found. ```lua ReplicaController.GetReplicaById(replica_id) --> [Replica] or nil ``` -------------------------------- ### Server Script: Initializing a Replica with WriteLib Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md This server script initializes a Replica instance, assigning a WriteLib to it. It then connects ClickDetector events to trigger WriteLib functions using Replica:Write(). Ensure the WriteLib module is accessible, e.g., in ReplicatedStorage. ```lua local SodaMachineReplicaClassToken = ReplicaService.NewClassToken("SodaMachine") local WriteLib = game.ReplicatedStorage:FindFirstChild("WriteLib") local model -- A Model instance local replica = ReplicaService.NewReplica({ ClassToken = CoinReplicaClassToken, Tags = {Model = model}, Data = { Cans = { Cola = 10, Lemonade = 10, RootBeer = 10, }, CoinsInside = 0, }, -- Replica does not create a deep copy! Replication = "All", WriteLib = WriteLib }) local cola_click_detector -- Assume this is a ClickDetector of a cola button local restock_click_detector -- Assume this is a ClickDetector of a restock button coca_click_detector.MouseClick:Connect(function() replica:Write("TakeCan", "Cola", 1) end) restock_click_detector.MouseClick:Connect(function() replica:Write("RestockAll", 1, 10) end) ``` -------------------------------- ### Initialize Replicas with ReplicaService Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Create new replicas with specific replication settings, data, and optional WriteLib for custom mutators. ```lua local ReplicaService = require(game:GetService("ServerScriptService").ReplicaService) local PlayerDataToken = ReplicaService.NewClassToken("PlayerData") -- Create a replica that replicates to all players local globalReplica = ReplicaService.NewReplica({ ClassToken = PlayerDataToken, Data = { Coins = 100, Level = 1, Inventory = {}, }, Replication = "All", -- Replicate to everyone }) -- Create a replica for a specific player local player = game.Players:GetPlayers()[1] local playerReplica = ReplicaService.NewReplica({ ClassToken = ReplicaService.NewClassToken("PrivatePlayerData"), Tags = {Player = player}, -- Tags for identification Data = { SecretKey = "abc123", PrivateSettings = {SoundEnabled = true}, }, Replication = player, -- Only replicate to this player }) -- Create a replica with a WriteLib for custom mutators local WriteLib = game.ReplicatedStorage:WaitForChild("PlayerWriteLib") local advancedReplica = ReplicaService.NewReplica({ ClassToken = ReplicaService.NewClassToken("AdvancedPlayerData"), Tags = {Player = player}, Data = {Coins = 0, Items = {}}, Replication = "All", WriteLib = WriteLib, }) ``` -------------------------------- ### Initialize Server-Side Replica Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Handles player data creation and event processing on the server. Requires the ReplicaService module. ```lua -- Server Script: PlayerDataServer.server.lua (ServerScriptService) local ReplicaService = require(game:GetService("ServerScriptService").ReplicaService) local Players = game:GetService("Players") local PlayerDataToken = ReplicaService.NewClassToken("PlayerData") local WriteLib = game.ReplicatedStorage:WaitForChild("PlayerDataWriteLib") local PlayerReplicas = {} Players.PlayerAdded:Connect(function(player) { local replica = ReplicaService.NewReplica({ ClassToken = PlayerDataToken, Tags = {Player = player}, Data = { Coins = 100, Level = 1, Experience = 0, Inventory = { {Name = "Starter Sword", Quantity = 1}, {Name = "Health Potion", Quantity = 5}, }, }, Replication = "All", WriteLib = WriteLib, }) PlayerReplicas[player] = replica replica:AddCleanupTask(function() { PlayerReplicas[player] = nil }) -- Handle player requests replica:ConnectOnServerEvent(function(requestPlayer, action, ...) { if requestPlayer ~= player then return end -- Security check if action == "BuyItem" then local itemName, price = ... if replica.Data.Coins >= price then replica:Write("AddCoins", -price) replica:Write("AddItem", itemName, 1) replica:FireClient(player, "PurchaseSuccess", itemName) else replica:FireClient(player, "PurchaseFailed", "Not enough coins") } } }) }) Players.PlayerRemoving:Connect(function(player) { local replica = PlayerReplicas[player] if replica then replica:Destroy() } }) ``` -------------------------------- ### Client-Side Replica Initialization and Change Listening Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/tutorial/basic_usage.md This client script requires ReplicaController and sets up a callback for when a 'TestReplica' is created. It prints the initial value and listens for changes to the 'Value' field. Call ReplicaController.RequestData() only once globally. ```lua local ReplicaController = require(game.ReplicatedStorage.ReplicaController) ReplicaController.ReplicaOfClassCreated("TestReplica", function(replica) print("TestReplica received! Value:", replica.Data.Value) replica:ListenToChange({"Value"}, function(new_value) print("Value changed:", new_value) end) end) ReplicaController.RequestData() -- This function should only be called once -- in the entire codebase! Read the documentation for more info. ``` -------------------------------- ### Connect to Server Event Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Simulates RemoteEvent.OnServerEvent behavior for the replica. ```lua Replica:ConnectOnServerEvent(listener) --> [ScriptConnection] (player, params...) ``` -------------------------------- ### Server-Side Replica Creation and Update Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/tutorial/basic_usage.md This script runs on the server to initialize a new replica with a 'TestReplica' class token and a 'Value' field. It then increments this value every second. Ensure ReplicaService is correctly required from ServerScriptService. ```lua local ReplicaService = require(game.ServerScriptService.ReplicaService) local test_replica = ReplicaService.NewReplica({ ClassToken = ReplicaService.NewClassToken("TestReplica"), Data = {Value = 0}, Replication = "All", }) while task.wait(1) do test_replica:SetValue({"Value"}, test_replica.Data.Value + 1) end ``` -------------------------------- ### WriteLib Structure and Usage Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Demonstrates the structure of a WriteLib ModuleScript and how to use Replica:Write() to call its mutator functions. ```APIDOC ## WriteLib ModuleScript Structure ### Description A `ModuleScript` containing a dictionary of mutator functions that can be triggered using `Replica:Write()`. ### Example Structure (WriteLib.lua) ```lua local WriteLib = { -- Mutator functions will receive the first parameter as the -- Replica being mutated; Custom parameters passed with -- Replica:Write() will follow RestockAll = function(replica, restock_count, max_count) for soda_name, old_count in pairs(replica.Data.Cans) do replica:SetValue( {"Cans", soda_name}, math.min(old_count + restock_count, max_count) ) end end, TakeCan = function(replica, soda_name, amount) --> amount_taken local old_count = replica.Data.Cans[soda_name] or 0 local amount_taken = math.min(old_count, amount) if amount_taken > 0 then replica:SetValue({"Cans", soda_name}, old_count - amount_taken) end return amount_taken end, AddCoins = function(replica, coin_count) replica:SetValue({"CoinsInside"}, replica.Data.CoinsInside + coin_count) end, TakeAllCoins = function() --> coins_taken local coins = replica.Data.CoinsInside replica:SetValue({"CoinsInside"}, 0) replica:Write("RestockAll", 1, 10) -- WriteLibs can use their own mutators! return coins end } return WriteLib ``` ## Replica:Write() ### Description Calls a function within a WriteLib that has been assigned to this `Replica` for both the server and all clients that have this `Replica` replicated to them. ### Method `Replica:Write(function_name, params...) ### Parameters - **function_name** (string) - The name of the mutator function to call within the WriteLib. - **params...** (any) - Custom parameters to pass to the mutator function. ### Returns - **params...** (any) - Anything the called write function returns. ### Server Example (Script.server.lua) ```lua local WriteLib = game.ReplicatedStorage:FindFirstChild("WriteLib") local replica = ReplicaService.NewReplica({ -- ... other replica properties WriteLib = WriteLib }) -- Example: Triggering TakeCan mutator replica:Write("TakeCan", "Cola", 1) -- Example: Triggering RestockAll mutator replica:Write("RestockAll", 1, 10) ``` ### Client Example (LocalScript.client.lua) ```lua ReplicaController.ReplicaOfClassCreated("SodaMachine", function(replica) replica:ListenToWrite("TakeCan", function(soda_name, amount) print(tostring(amount) .. " can(s) of " .. soda_name .. " have been taken.") end) replica:ListenToWrite("RestockAll", function(restock_count, max_count) print("Replica has been restocked!") end) end) ``` ``` -------------------------------- ### Client Script: Listening to WriteLib Events Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md This client script demonstrates how to listen for WriteLib function calls and data changes on a Replica. It uses Replica:ListenToWrite() to react to specific mutator functions and Replica:ListenToChange() for data property updates. Listeners are automatically cleaned up when the Replica is destroyed. ```lua ReplicaController.ReplicaOfClassCreated("SodaMachine", function(replica) local machine_model = replica.Tags.Model replica:ListenToWrite("TakeCan", function(soda_name, amount) -- Play sound on the client? print(tostring(amount) .. " can(s) of " .. soda_name .. " have been taken from " .. tostring(machine_model)) end) replica:ListenToWrite("RestockAll", function(restock_count, max_count) print(tostring(machine_model) .. " has been restocked! (" .. tostring(restock_count) .. " each)") end) replica:ListenToChange({"Cans", "Cola"}, function(new_value) print("Coke can count has changed:", new_value) end) -- Notice: You don't need to disconnect Replica listeners as the listeners -- will be forgotten when the Replica is destroyed end) ``` -------------------------------- ### Client: Request Initial Replica Data Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Call ReplicaController.RequestData() on the client to fetch initial replica data from the server. It's crucial to connect all listeners for ReplicaOfClassCreated and NewReplicaSignal before calling RequestData. Use InitialDataReceivedSignal:Wait() to pause execution until all initial data is received. ```lua local ReplicaController = require(game:GetService("ReplicatedStorage"):WaitForChild("ReplicaController")) -- IMPORTANT: Connect all listeners BEFORE calling RequestData ReplicaController.ReplicaOfClassCreated("PlayerData", function(replica) print("Received PlayerData replica") end) ReplicaController.ReplicaOfClassCreated("WorldState", function(replica) print("Received WorldState replica") end) -- Now request data from server (call only once!) ReplicaController.RequestData() -- Wait for initial data if needed if not ReplicaController.InitialDataReceived then ReplicaController.InitialDataReceivedSignal:Wait() end print("All initial replicas received!") ``` -------------------------------- ### Create Class Tokens with ReplicaService Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Initialize unique class tokens to prevent naming collisions when creating replicas. Tokens must be created once per class name. ```lua local ReplicaService = require(game:GetService("ServerScriptService").ReplicaService) -- Create class tokens (do this once, typically at module initialization) local PlayerDataToken = ReplicaService.NewClassToken("PlayerData") local InventoryToken = ReplicaService.NewClassToken("Inventory") local WorldChunkToken = ReplicaService.NewClassToken("WorldChunk") -- Attempting to create a duplicate token will error: -- local DuplicateToken = ReplicaService.NewClassToken("PlayerData") -- ERROR! ``` -------------------------------- ### Listen for Any Replica Creation Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Connect to ReplicaController.NewReplicaSignal to be notified whenever any replica is created client-side. Ensure listeners are connected before requesting data. ```lua ReplicaController.NewReplicaSignal [ScriptSignal] (replica) ``` ```lua ReplicaController.NewReplicaSignal:Connect(function(replica) print("Replica created:", replica:Identify()) end) ``` -------------------------------- ### Create a New Replica Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Instantiate a new replica using ReplicaService.NewReplica. The Data table is not deep-copied, and direct modification after wrapping is discouraged; use mutators instead. ```lua local PlayerStatsReplicaClassToken = ReplicaService.NewClassToken("PlayerStats") local player -- A Player instance local data = {Coins = 100} local replica = ReplicaService.NewReplica({ ClassToken = PlayerStatsReplicaClassToken, Tags = {Player = player}, Data = data, -- Replica does not create a deep copy! Replication = "All", }) print(replica.Data == data) --> true print(replica.Data.Coins) --> 100 replica:SetValue({"Coins"}, 420) print(data.Coins, replica.Data.Coins) --> 420 420 ``` -------------------------------- ### Listen to New Key Creation Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Registers a listener for when a new key is created inside a path. ```lua Replica:ListenToNewKey(path, listener) --> [ScriptConnection] -- listener [function] (new_value, new_key) ``` -------------------------------- ### Request Replica Data from Server Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Call ReplicaController.RequestData() to initiate the server sending replica data to the client. All listeners for replica creation events should be connected before this call. ```lua ReplicaController.RequestData() ``` -------------------------------- ### Client: Listen for Replica Creation Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Use ReplicaController.ReplicaOfClassCreated to listen for the creation of specific replica types on the client. A generic listener can be set up with NewReplicaSignal:Connect(). Remember to call ReplicaController.RequestData() to initiate data fetching. ```lua local ReplicaController = require(game:GetService("ReplicatedStorage"):WaitForChild("ReplicaController")) -- Listen for PlayerData replicas ReplicaController.ReplicaOfClassCreated("PlayerData", function(replica) local player = replica.Tags.Player print("Received PlayerData for:", player.Name) print("Initial coins:", replica.Data.Coins) -- Access nested replicas immediately for _, child in ipairs(replica.Children) do print("Child replica:", child.Class) end end) -- Listen for inventory replicas ReplicaController.ReplicaOfClassCreated("Inventory", function(replica) local items = replica.Data.Items print("Inventory received with", #items, "items") -- Set up UI bindings, etc. end) -- Generic listener for all replicas ReplicaController.NewReplicaSignal:Connect(function(replica) print("Any replica created:", replica:Identify()) end) ReplicaController.RequestData() ``` -------------------------------- ### ReplicaController Methods Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Methods for managing replica creation, retrieval, and data synchronization on the client. ```APIDOC ## ReplicaController.ReplicaOfClassCreated ### Description Listens to the creation of replicas of a specific class on the client-side. ### Parameters - **replica_class** (string) - Required - The class name to listen for. - **listener** (function) - Required - Callback function receiving the replica instance. ## ReplicaController.NewReplicaSignal ### Description A signal that fires every time a replica is created client-side. ## ReplicaController.GetReplicaById ### Description Retrieves a replica instance by its unique ID. ### Parameters - **replica_id** (number) - Required - The ID of the replica to retrieve. ## ReplicaController.RequestData ### Description Requests the server to start sending replica data. Should be called after setting up listeners. ``` -------------------------------- ### Listen to Child Added Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Registers a listener for when a new child replica is created. ```lua Replica:ListenToChildAdded(listener) --> [ScriptConnection] -- listener [function] (replica) ``` -------------------------------- ### Listen to New Keys Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Use ListenToNewKey to detect when new entries are added to dynamic data structures like inventories or leaderboards. ```lua local ReplicaController = require(game:GetService("ReplicatedStorage"):WaitForChild("ReplicaController")) ReplicaController.ReplicaOfClassCreated("Inventory", function(replica) -- Listen for new items being added to inventory replica:ListenToNewKey({"Items"}, function(newValue, newKey) print("New item added:", newKey, "=", newValue) -- Create UI element for new item end) -- Listen for new player entries in a leaderboard replica:ListenToNewKey({"Leaderboard"}, function(score, playerName) print(playerName, "joined leaderboard with score:", score) end) -- Listen at root level for any new top-level keys replica:ListenToNewKey({}, function(value, key) print("New root key:", key) end) end) ReplicaController.RequestData() ``` -------------------------------- ### Listen to Custom WriteLib Calls Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Use ListenToWrite to trigger logic when specific WriteLib functions are executed on the server. ```lua local ReplicaController = require(game:GetService("ReplicatedStorage"):WaitForChild("ReplicaController")) ReplicaController.ReplicaOfClassCreated("SodaMachine", function(replica) local machineModel = replica.Tags.Model -- Listen for specific write functions replica:ListenToWrite("TakeCan", function(sodaName, amount) print(amount, "can(s) of", sodaName, "taken!") -- Play dispensing animation/sound end) replica:ListenToWrite("RestockAll", function(restockAmount, maxCount) print("Machine restocked! Added", restockAmount, "to each") -- Play restocking animation end) replica:ListenToWrite("AddCoins", function(amount) print(amount, "coins inserted") -- Play coin sound end) end) ReplicaController.RequestData() ``` -------------------------------- ### ReplicaService.NewReplica Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Creates a new Replica with specified parameters including class token, data, tags, replication settings, parent, and optional WriteLib. ```APIDOC ## ReplicaService.NewReplica ### Description Creates a new Replica with specified parameters including class token, data, tags, replication settings, parent, and optional WriteLib. ### Method `ReplicaService.NewReplica(options: table)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **ClassToken** (token) - Required - The class token obtained from `NewClassToken`. - **Data** (table) - Required - The initial state data for the replica. - **Tags** (table) - Optional - Key-value pairs for identifying the replica. - **Replication** (string or Player object) - Required - Specifies who the replica should be replicated to. Can be "All", a specific Player object, or a table of Player objects. - **WriteLib** (Instance) - Optional - A WriteLib instance for custom mutator functions. - **Parent** (Instance) - Optional - The parent of the replica object. ### Request Example ```lua local ReplicaService = require(game:GetService("ServerScriptService").ReplicaService) local PlayerDataToken = ReplicaService.NewClassToken("PlayerData") -- Create a replica that replicates to all players local globalReplica = ReplicaService.NewReplica({ ClassToken = PlayerDataToken, Data = { Coins = 100, Level = 1, Inventory = {}, }, Replication = "All", -- Replicate to everyone }) -- Create a replica for a specific player local player = game.Players:GetPlayers()[1] local playerReplica = ReplicaService.NewReplica({ ClassToken = ReplicaService.NewClassToken("PrivatePlayerData"), Tags = {Player = player}, -- Tags for identification Data = { SecretKey = "abc123", PrivateSettings = {SoundEnabled = true}, }, Replication = player, -- Only replicate to this player }) -- Create a replica with a WriteLib for custom mutators local WriteLib = game.ReplicatedStorage:WaitForChild("PlayerWriteLib") local advancedReplica = ReplicaService.NewReplica({ ClassToken = ReplicaService.NewClassToken("AdvancedPlayerData"), Tags = {Player = player}, Data = {Coins = 0, Items = {}}, Replication = "All", WriteLib = WriteLib, }) ``` ### Response #### Success Response (200) Returns the newly created Replica object. #### Response Example (No direct response example, as it returns a Replica object) ``` -------------------------------- ### Create nested structures with ReplicaService.Temporary Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Use ReplicaService.Temporary as a parent to build nested structures before attaching them to a replicated parent, ensuring children are sent to the client in a single update. ```lua local ReplicaService = require(game:GetService("ServerScriptService").ReplicaService) local ContainerToken = ReplicaService.NewClassToken("Container") local ItemToken = ReplicaService.NewClassToken("Item") -- Create the container that will be replicated local containerReplica = ReplicaService.NewReplica({ ClassToken = ContainerToken, Replication = "All", }) -- Build nested structure using Temporary parent -- This ensures children are sent together with parent local itemReplica1 = ReplicaService.NewReplica({ ClassToken = ItemToken, Tags = {ItemId = 1}, Data = {Name = "Sword", Damage = 10}, Parent = ReplicaService.Temporary, -- Temporarily non-replicated }) local itemReplica2 = ReplicaService.NewReplica({ ClassToken = ItemToken, Tags = {ItemId = 2}, Data = {Name = "Shield", Defense = 5}, Parent = itemReplica1, -- Child of itemReplica1 }) -- Now move the entire structure to be replicated -- Client will receive parent with all children at once itemReplica1:SetParent(containerReplica) -- On client: containerReplica.Children will include itemReplica1 immediately ``` -------------------------------- ### Create Temporary Replicas in ReplicaService Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Use ReplicaService.Temporary to group nested replicas so they are replicated to clients as a single structure. ```lua local UseTemporary = true -- Set to false to make the replicas be -- replicated separately local ContainerReplica = ReplicaService.NewReplica({ ClassToken = ReplicaService.NewClassToken("SingletonContainerReplica"), Replication = "All", }) local ReplicaClassToken1 = ReplicaService.NewClassToken("Class1") local ReplicaClassToken2 = ReplicaService.NewClassToken("Class2") local parent = ContainerReplica if UseTemporary == true then parent = ReplicaService.Temporary end local nested_replica = ReplicaService.NewReplica({ ClassToken = ReplicaClassToken1, -- "Class1" Parent = parent, }) local child_replica = ReplicaService.NewReplica({ ClassToken = ReplicaClassToken2, -- "Class2" Parent = nested_replica, }) nested_replica:SetParent(ContainerReplica) -- Sets Parent to ContainerReplica -- if it wasn't already parented to ContainerReplica ``` ```lua ReplicaController.ReplicaOfClassCreated("Class1", function(replica) print(#replica.Children) --> Will print 1 when UseTemporary is set to true -- or 0 when UseTemporary is set to false coroutine.wrap(function() wait() print(#replica.Children) --> Will always print 1 when UseTemporary -- is set to true and is very likely, but not guaranteed to -- print 1 when UseTemporary is set to false end)() end) ReplicaController.RequestData() -- Only using here for testing purposes -- ReplicaController.RequestData() should only be called once in the -- entire codebase! ``` -------------------------------- ### Fire Server Events with Replica:FireServer() Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Simulates the behavior of RemoteEvent:FireServer(), allowing the client to send parameters to the server. ```lua Replica:FireServer(params...) ``` -------------------------------- ### Server-side Replica Communication Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Use FireClient and FireAllClients to send signals from the server to clients. ConnectOnServerEvent listens for incoming client signals. Ensure ReplicaService is required before use. ```lua local ReplicaService = require(game:GetService("ServerScriptService").ReplicaService) local GameStateToken = ReplicaService.NewClassToken("GameState") local replica = ReplicaService.NewReplica({ ClassToken = GameStateToken, Data = {Round = 1, TimeLeft = 60}, Replication = "All", }) -- Listen for client signals replica:ConnectOnServerEvent(function(player, action, ...) if action == "RequestRespawn" then print(player.Name, "requested respawn") -- Handle respawn logic replica:FireClient(player, "RespawnGranted", Vector3.new(0, 10, 0)) elseif action == "ChatMessage" then local message = ... -- Broadcast to all players replica:FireAllClients("PlayerChat", player.Name, message) end end) -- Send notification to specific player local function notifyPlayer(player, message) replica:FireClient(player, "Notification", message) end -- Broadcast event to all subscribed clients local function announceRoundStart() replica:FireAllClients("RoundStarted", replica.Data.Round) end ``` -------------------------------- ### Listen to Value Changes Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Use ListenToChange to react to updates at specific data paths. Listeners are automatically cleaned up when the replica is destroyed. ```lua local ReplicaController = require(game:GetService("ReplicatedStorage"):WaitForChild("ReplicaController")) ReplicaController.ReplicaOfClassCreated("PlayerData", function(replica) -- Listen to top-level value changes replica:ListenToChange({"Coins"}, function(newValue, oldValue) print("Coins changed from", oldValue, "to", newValue) -- Update UI end) -- Listen to nested value changes replica:ListenToChange({"Stats", "Health"}, function(newValue, oldValue) print("Health:", oldValue, "->", newValue) if newValue <= 0 then print("Player died!") end end) -- String path also works replica:ListenToChange("Stats.Mana", function(newValue, oldValue) print("Mana changed:", newValue) end) -- Listeners are automatically cleaned when replica is destroyed end) ReplicaController.RequestData() ``` -------------------------------- ### Client-Server Communication with ConnectOnClientEvent and FireServer Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Implement client-side event handling and server communication using ConnectOnClientEvent to listen for server signals and FireServer to send signals to the server. This pattern is essential for real-time interactions and game state synchronization between clients and the server. ```lua local ReplicaController = require(game:GetService("ReplicatedStorage"):WaitForChild("ReplicaController")) ReplicaController.ReplicaOfClassCreated("GameState", function(replica) -- Listen for server signals replica:ConnectOnClientEvent(function(eventType, ...) if eventType == "RoundStarted" then local roundNumber = ... print("Round", roundNumber, "started!") elseif eventType == "Notification" then local message = ... print("Server notification:", message) elseif eventType == "PlayerChat" then local playerName, message = ... print("[Chat]", playerName .. ":", message) elseif eventType == "RespawnGranted" then local position = ... print("Respawning at", position) end end) -- Send signals to server local function requestRespawn() replica:FireServer("RequestRespawn") end local function sendChat(message) replica:FireServer("ChatMessage", message) end end) ReplicaController.RequestData() ``` -------------------------------- ### Replica:FireServer() Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Simulates firing an event to the server, mimicking the behavior of RemoteEvent:FireServer(). ```APIDOC ## Replica:FireServer() ### Description Simulates the behavior of [RemoteEvent:FireServer()](https://developer.roblox.com/en-us/api-reference/class/RemoteEvent#fireserver-tuple-arguments-). This function is used to send data or trigger actions on the server from the client. ### Method `FireServer` ### Endpoint N/A (This is a client-side method) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **params...** (any) - Optional - Any number of parameters to be sent to the server. These parameters will be passed to the server-side event listeners. ### Returns None ``` -------------------------------- ### Fire Client Events Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Methods to trigger events on specific clients or all connected clients. ```lua Replica:FireClient(player, params...) ``` ```lua Replica:FireAllClients(params...) ``` -------------------------------- ### Replica Object Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Properties and methods available on a Replica instance. ```APIDOC ## Replica Properties - **Data** (table) - Read-only state wrapped by the replica. - **Id** (number) - Read-only unique identifier. - **Class** (string) - Read-only class name. - **Tags** (table) - Read-only custom static identifiers. - **Parent** (Replica|nil) - Read-only reference to parent replica. - **Children** (table) - Read-only array of child replicas. ## Replica Methods ### Replica:IsActive Returns true if the replica is active, false if destroyed. ### Replica:Identify Returns a string description of the replica for debugging. ``` -------------------------------- ### Handle Purchase Events in Roblox Source: https://context7.com/madstudioroblox/replicaservice/llms.txt This snippet demonstrates how to handle purchase events, including successful purchases and failures, by listening to a server event. It prints the item name on success or the reason for failure. ```lua ReplicationService.OnEvent("PurchaseEvent", function(eventType, ...) if eventType == "PurchaseSuccess" then local itemName = ... print("Successfully purchased:", itemName) elseif eventType == "PurchaseFailed" then local reason = ... print("Purchase failed:", reason) end end) end end) -- Function to buy items local function buyItem(itemName, price) if MyPlayerReplica then MyPlayerReplica:FireServer("BuyItem", itemName, price) end end ReplicaController.RequestData() ``` -------------------------------- ### Consume Replica Data on Client Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Listens for replica creation and data changes on the client. Requires the ReplicaController module. ```lua -- Client Script: PlayerDataClient.client.lua (StarterPlayerScripts) local ReplicaController = require(game:GetService("ReplicatedStorage"):WaitForChild("ReplicaController")) local Players = game:GetService("Players") local LocalPlayer = Players.LocalPlayer local MyPlayerReplica = nil ReplicaController.ReplicaOfClassCreated("PlayerData", function(replica) { if replica.Tags.Player == LocalPlayer then MyPlayerReplica = replica print("My player data loaded!") print("Coins:", replica.Data.Coins) print("Level:", replica.Data.Level) -- Display initial inventory for i, item in ipairs(replica.Data.Inventory) do print("Slot", i, ":", item.Name, "x" .. item.Quantity) } -- Listen to coin changes replica:ListenToChange({"Coins"}, function(newCoins, oldCoins) { local diff = newCoins - oldCoins if diff > 0 then print("+" .. diff .. " coins! Total:", newCoins) else print(diff .. " coins. Total:", newCoins) } }) -- Listen to level changes replica:ListenToChange({"Level"}, function(newLevel) { print("LEVEL UP! Now level", newLevel) }) -- Listen to inventory changes via WriteLib replica:ListenToWrite("AddItem", function(itemName, quantity) { print("Received", quantity, "x", itemName) }) replica:ListenToWrite("RemoveItem", function(itemName, quantity) { print("Used/Lost", quantity, "x", itemName) }) -- Listen to server events replica:ConnectOnClientEvent(function(eventType, ...) { if eventType == "PurchaseSuccess" then ``` -------------------------------- ### Connect to Client Events with Replica:ConnectOnClientEvent() Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Connects a listener function to client-side events, similar to RemoteEvent.OnClientEvent. Returns a ScriptConnection. ```lua Replica:ConnectOnClientEvent(listener) --> [ScriptConnection] -- listener [function] (params...) ``` -------------------------------- ### Replica Lifecycle Management Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Manage replica lifecycles using AddCleanupTask, RemoveCleanupTask, and Destroy. Cleanup tasks automatically run when a replica is destroyed, ensuring resources like models or connections are released. Use IsActive to check the current state. ```lua local ReplicaService = require(game:GetService("ServerScriptService").ReplicaService) local EntityToken = ReplicaService.NewClassToken("Entity") local function createEntityReplica(model) local replica = ReplicaService.NewReplica({ ClassToken = EntityToken, Tags = {Model = model}, Data = {Health = 100}, Replication = "All", }) -- Add cleanup tasks that run when replica is destroyed replica:AddCleanupTask(model) -- Destroy the model -- Add a function cleanup task replica:AddCleanupTask(function() print("Entity replica destroyed, cleaning up...") end) -- Add a connection cleanup task local connection = game:GetService("RunService").Heartbeat:Connect(function() -- Update logic end) replica:AddCleanupTask(connection) return replica end local model = Instance.new("Part") model.Parent = workspace local entityReplica = createEntityReplica(model) -- Check if replica is still active print(entityReplica:IsActive()) --> true -- Destroy replica and all cleanup tasks entityReplica:Destroy() -- Model is destroyed, connection disconnected, function called print(entityReplica:IsActive()) --> false ``` -------------------------------- ### Signal for New Active Players Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md ReplicaService.NewActivePlayerSignal is a ScriptSignal that fires when a new player is added to ReplicaService.ActivePlayers. ```lua ReplicaService.NewActivePlayerSignal [ScriptSignal] (player) ``` -------------------------------- ### ReplicaService.NewReplica Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Creates a new replica object and immediately replicates it based on the specified replication settings. Replicas can be top-level or nested, and their replication behavior can be controlled via parameters. ```APIDOC ## ReplicaService.NewReplica ### Description Creates a replica and immediately replicates it to select active players based on replication settings of this `Replica` or the parent `Replica`. ### Method `ReplicaService.NewReplica(replica_params)` ### Parameters - **replica_params** (table): A table containing parameters for the replica. - **ClassToken** (ReplicaClassToken) - Required - Sets `Replica.Class` to the string provided in `ReplicaService.NewClassToken(class_name)`. - **Tags** (table) - Optional (Default: `{}`) - A dictionary of identifiers (e.g., `{Part = part, Player = player, ...}`). Tags cannot be changed after creation. - **Data** (table) - Optional (Default: `{}`) - A table representing the state to be replicated. Retains table reference. - **Replication** (string or table) - Optional (Default: `{}`) - Controls replication. Can be "All" to replicate to everyone, a table of `{Player = true, ...}` for selective replication, or a single `Player` instance. - **Parent** (Replica) - Optional (Default: `nil`) - Sets the parent replica for nested replicas. If `nil`, creates a top-level replica. - **WriteLib** (ModuleScript) - Optional (Default: `nil`) - A `ModuleScript` to assign write functions (mutator functions) to this replica. ### Notes - `Replication` and `Parent` parameters are mutually exclusive. Providing a `Parent` creates a nested replica, which inherits replication settings. `nil` Parent creates a top-level replica with its own replication settings. - Top-level replicas force their replication settings to all descendant nested replicas. ``` -------------------------------- ### Manage Nested Replicas with ListenToChildAdded and FindFirstChildOfClass Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Utilize ListenToChildAdded to react to new children entering a replica hierarchy and FindFirstChildOfClass to locate a specific child by its class name. This is useful for managing complex game states and entity interactions within rooms or other containers. ```lua local ReplicaController = require(game:GetService("ReplicatedStorage"):WaitForChild("ReplicaController")) ReplicaController.ReplicaOfClassCreated("Room", function(roomReplica) print("Room received:", roomReplica.Tags.RoomId) -- Handle existing children for _, child in ipairs(roomReplica.Children) do print("Existing entity in room:", child:Identify()) end -- Listen for new children being added roomReplica:ListenToChildAdded(function(childReplica) print("New entity entered room:", childReplica.Class) if childReplica.Class == "Player" then -- Handle player-specific logic elseif childReplica.Class == "Enemy" then -- Handle enemy-specific logic end end) -- Find specific child by class local bossReplica = roomReplica:FindFirstChildOfClass("Boss") if bossReplica then print("Boss found in room with health:", bossReplica.Data.Health) end end) ReplicaController.RequestData() ``` -------------------------------- ### Listen for Specific Replica Class Creation Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Use ReplicaController.ReplicaOfClassCreated to listen for client-side creation of replicas belonging to a specific class. This is the preferred method for obtaining references to replicas on the client. ```lua ReplicaController.ReplicaOfClassCreated(replica_class, listener) --> [ScriptConnection] listener(replica) ``` ```lua ReplicaController.ReplicaOfClassCreated("Flower", function(replica) print("Flower replica created:", replica:Identify()) print(replica.Class == "Flower") --> true end) ``` -------------------------------- ### Add Cleanup Task to Replica Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Signs up a task, object, instance, or function to be ran or destroyed when the Replica is destroyed. The cleanup task is performed instantly if the Replica is already destroyed. ```lua Replica:AddCleanupTask(task) -- task [function] or [Instance] or [Object] (with :Destroy() or :Disconnect()) ``` ```lua local FlowerReplicaClassToken = ReplicaService.NewClassToken("Flower") local flower_model -- A Model instance local replica = ReplicaService.NewReplica({ ClassToken = FlowerReplicaClassToken, Tags = {Model = flower_model}, Data = { HasBees = false, HoneyScore = 10, }, Replication = "All", }) replica:AddCleanupTask(flower_model) replica:Destroy() -- Destroys the replica for all subscribed clients first, -- then runs all the cleanup tasks including destroying the flower_model ``` -------------------------------- ### Replica:ListenToRaw Source: https://context7.com/madstudioroblox/replicaservice/llms.txt Provides a low-level listener for all built-in mutator operations, receiving raw parameters for debugging and logging purposes. ```APIDOC ## Replica:ListenToRaw ### Description Low-level listener that receives all built-in mutator operations with raw parameters. ### Method `ListenToRaw` (called on a replica object) ### Parameters - `callback` (function) - Required - A function that will be called with `actionName`, `pathArray`, and subsequent arguments representing the data change. ### Request Example ```lua local ReplicaController = require(game:GetService("ReplicatedStorage"):WaitForChild("ReplicaController")) ReplicaController.ReplicaOfClassCreated("DebugReplica", function(replica) replica:ListenToRaw(function(actionName, pathArray, ...) local pathStr = table.concat(pathArray, ".") if actionName == "SetValue" then local value = ... print("[SetValue]", pathStr, "=", value) elseif actionName == "SetValues" then local values = ... print("[SetValues]", pathStr, values) elseif actionName == "ArrayInsert" then local value, newIndex = ... print("[ArrayInsert]", pathStr, "index:", newIndex, "value:", value) elseif actionName == "ArraySet" then local index, value = ... print("[ArraySet]", pathStr, "[" .. index .. "]", "=", value) elseif actionName == "ArrayRemove" then local index, oldValue = ... print("[ArrayRemove]", pathStr, "[" .. index .. "]", "was:", oldValue) end end) end) ReplicaController.RequestData() ``` ### Response This method does not return a value directly, but invokes the provided callback function upon data changes. ``` -------------------------------- ### Replicate Replica to Clients Source: https://github.com/madstudioroblox/replicaservice/blob/master/docs/api.md Modifies subscription settings for top-level replicas to control which players receive updates. ```lua Replica:ReplicateFor("All") -- Replicates the Replica to everyone in the game and -- everyone who will join in the future Replica:ReplicateFor(player) -- Selectively replicates the replica to a Player; -- Will not alter replication when the Replica is already replicated to "All" ```