BetterStore is a high-performance server-side data controller designed
to handle player save profiles safely and efficiently. It works by linking
Roblox’s cloud DataStoreService directly with loleris’s ReplicaService
framework.
Instead of manually firing network events to update the client, any changes
made on the server through this module are automatically synchronized down
to the player’s screen in real-time.
KEY ARCHITECTURAL FEATURES:
-
SESSION LOCKING (Race Condition Defense)
When a player joins a server, this module places a unique token lock (using the
server’s JobId) onto their cloud save data. If the player leaves and quickly joins
a different server, the new server will read this lock, see that it is still active,
and refuse to load the profile until the old server releases it or the 5-minute
safety timeout passes. This completely prevents item duplication exploits. -
DEEP DATA RECONCILIATION
When you release game updates that add new variables, items, or settings to your
default data template, old players logging in will automatically receive those
new fields. The module recursively walks down your data trees to insert missing
keys without touching or resetting the player’s existing progress. -
DENSE BINARY SERIALIZATION (Folders & Models)
Saving physical instances like parts, folders, or models directly into a DataStore
is impossible. This module leverages native ‘SerializationService’ memory buffers
to compress entire folders of parts into compact binary text codes. This method
preserves container names and index orders while saving up to 90% more cloud storage
space than traditional position-logging methods. -
NETWORK BATCH MANAGEMENT (Bulk Operations)
Modifying large lists (like inserting 20 starter items or clearing an entire inventory)
one item at a time creates heavy network traffic. This module solves that by running
bulk operations locally on the server first, then sending the finalized table over
the network in one single data packet, preventing lag spikes. -
AUTO-CLEANUP & MEMORY FLUSHING
To protect your game server from performance degradation over long runtimes, a
comprehensive cleanup routine is executed every time a player leaves. It completely
destroys active Replicas, disconnects signal listeners, and clears local memory
caches to ensure flawless garbage collection.
HOW TO USE ON THE SERVER:
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BetterStore = require(ReplicatedStorage:WaitForChild("BetterStore")) -- Require it
local PlayerDataManager = BetterStore.new({
profileIndex = "GameSaves_v5", -- optional profileIndex [Names the Data]
profileToken = "Default", -- optional profileToken [Creates and Names the Replication]
template = { -- required template [the placeholder for your data]
Cash = 100,
}
})
Players.PlayerAdded:Connect(function(player)
PlayerDataManager:load(player) -- [Loads Data]
PlayerDataManager:set(player, {"Cash"}, 500) -- [Sets anything in the template to a new value]
end)
Players.PlayerRemoving:Connect(function(player)
PlayerDataManager:save(player) -- [Save Data]
end)
HOW TO USE ON THE CLIENT
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local BetterStore = require(ReplicatedStorage:WaitForChild("BetterStore")) -- Require it
local Controller = require(ReplicatedStorage:WaitForChild("BetterStore"):WaitForChild("ReplicaController")) -- Grab the Replica Controller to Access it form the client
Controller.ReplicaOfClassCreated("Default", function(replica) -- "Default" Would be the DataToken you have on the server
replica:OnChange({"Cash"}, function(newCash, oldCash) -- OnChange Event -- Fires when a value changes
print(`[CASH UPDATE] Changed from {oldCash} to {newCash}`) -- prints this
end)
end)
Documentation (Use for More Ussage of BetterStore / ProfileStore2)
Module Link
Download File (38.5 KB)