ReduxWrapper
This module is an alternative to ProfileService made to exactly replicate it but without all of the session lock stuff which some people might not need, manipulating data on ProfileService is more complicated than it should be sometimes; session-locking is not as useful sometimes either.
So, I’d ask of you all to not come and yell at me for “oh my god profileservice is better!!1!” because this module was made just to lighten it and make it easier to use.
This code isn’t complex at all, and this requires a bit intermediate scripting knowledge in order to setup!
--!strict
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local ContentProvider = game:GetService("ContentProvider")
local HttpService = game:GetService("HttpService")
local DataStoreService = game:GetService("DataStoreService")
local ReduxWrapper = {};
ReduxWrapper.waitForRequestBudget = function(requestType)
local currentBudget = DataStoreService:GetRequestBudgetForRequestType(requestType);
while true do
if currentBudget < 1 then
currentBudget = DataStoreService:GetRequestBudgetForRequestType(requestType)
task.wait(2.5)
else
break
end
end
end
ReduxWrapper.new = function(dataName, dataTemplate)
local dataObj = DataStoreService:GetDataStore(dataName);
local method = {};
function method:LoadProfileAsync(key)
local profileMethods = {};
local success, err;
repeat
ReduxWrapper.waitForRequestBudget(Enum.DataStoreRequestType.GetAsync);
success, err = pcall(dataObj.GetAsync, dataObj, key)
until success
local profileData = err;
if profileData == nil then
profileData = {
MetaData = {
ProfileCreateTime = os.time();
LastUpdated = os.time();
};
Data = {}
};
end
profileMethods.Data = profileData.Data;
function profileMethods:AddUserId(userId)
profileData.MetaData.UserId = userId;
end
function profileMethods:Reconcile()
local function populateData(dataTemplate, data)
for key, value in dataTemplate do
if type(value) == "table" then
if not data[key] then
data[key] = {}
end
populateData(value, data[key])
else
if not data[key] then
data[key] = value
end
end
end
end
populateData(dataTemplate, profileMethods.Data)
end
function profileMethods:GetMetaTags()
return profileData.MetaData;
end
function profileMethods:Save(noWait)
local success, err;
repeat
if not noWait then
ReduxWrapper.waitForRequestBudget(Enum.DataStoreRequestType.UpdateAsync);
end
success, err = pcall(dataObj.UpdateAsync, dataObj, key, function()
return {
MetaData = profileData.MetaData;
Data = profileMethods.Data;
};
end)
until success
end
function profileMethods:Release()
table.clear(profileMethods)
end
return profileMethods
end
return method
end
return ReduxWrapper
API Usage:
local profileStore = ReduxWrapper.new(datastoreName: string, datastoreTemplate: table)
→ Constructs a new datastore with the following “datastoreName” and “datastoreTemplate” to store
local profile = profileStore:LoadProfileAsync(keyName: string)
→ Returns a profile object from the datastore with all the exposed methods and profile.Data value
profile:AddUserId(userId: number)
→ Sets the UserId in the Meta Tags section which makes it easier to handle GDPR requests sent by Roblox
profile:Reconcile
→ Reconciles all of the missing values from the DataTemplate that weren’t in the current profile.Data value
profile:GetMetaTags()
→ This returns a table with the Meta Tag data which is the following:
- ProfileCreateTime: number
- LastUpdated: number
- UserId: number (optional)
profile:Save()
attempts to save the current profile.Data value to the profileStore
Saving and Modifying Data:
It’s simple to save and modify data using ReduxWrapper, matter of fact it’s the exact same way ProfileService does it, all you have to do is :LoadProfileAsync and then change the .Data value to whatever you desire.
Example code:
local ProfileStore = ReduxWrapper.new("PlayerData", {
Coins = 0;
Level = 3;
})
local profile = ProfileStore:LoadProfileAsync("Player_1")
profile:Reconcile()
profile.Data.Coins = 55;
profile:Save()
Obviously this is very bare bones, but this explains to you what you can do in order to save data.
Thank you for reading, This probably won’t be updated; also global updates are not a thing.