Hello everyone! I have been utilizing various online sources to create a Datastore that I believed was functioning effectively. It involved packing and unpacking data written on a table to the player, allowing me to easily integrate this Datastore into any of my games. Unfortunately, while the Datastore works for a single player, it completely disregards any other players who join the game. Strangely enough, none of the desired folders and values are added to the player when they join for the first time if there is already another player in the game.
Here is the script for the Datastore:
local module = require(script.unite)
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local dataStore = DataStoreService:GetDataStore("datastore_021")
local default = {
SessionLock = false,
folder = {
{
folder_name = "info",
children = {
{
int_name = "level",
value = 0,
children = {
{
int_name = "xp_needed",
value = 25
};
{
int_name = "xp",
value = nil
};
};
};
{
int_name = "wins",
value = 0,
};
{
bool_name = "music_enabled",
value = true
};
}
},
}
}
local updateAsync = Enum.DataStoreRequestType.UpdateAsync
local function waitForRequestBudget()
local currentBudget = DataStoreService:GetRequestBudgetForRequestType(updateAsync)
while currentBudget < 1 do
currentBudget = DataStoreService:GetRequestBudgetForRequestType(updateAsync)
wait(5)
end
end
local function setUp(player)
local name = player.Name
local userId = player.UserId
local key = "Player_" .. userId
local success, data, shouldWait
repeat
waitForRequestBudget()
success, data = pcall(dataStore.UpdateAsync, dataStore, key, function(oldData)
oldData = oldData or default
if oldData.SessionLock then
if os.time() - oldData.SessionLock < 1800 then
shouldWait = true
else
oldData.SessionLock = os.time()
data = oldData
return data
end
else
oldData.SessionLock = os.time()
data = oldData
return data
end
end)
if shouldWait then
task.wait(5)
shouldWait = false
end
until (success and data) or not Players:FindFirstChild(name)
if success and data then
data = module.unpack(player, data.folder)
end
end
local function save(player, dontLeave, dontWait)
local userId = player.UserId
local key = "Player_" .. userId
local player_folder = player:FindFirstChild("info")
local to_pack = {}
module.pack(player_folder, to_pack)
--warn(to_pack)
local success
repeat
if not dontWait then
waitForRequestBudget()
end
success = pcall(dataStore.UpdateAsync, dataStore, key, function(oldData)
oldData = oldData or default
oldData.folder = to_pack
oldData.SessionLock = dontLeave and os.time() or nil
return oldData
end)
until success
end
local function onShutdown()
if RunService:IsStudio() then
task.wait(2)
else
local allPlayers = Players:GetPlayers()
local leftPlayers = #allPlayers
for _, player in ipairs(allPlayers) do
coroutine.wrap(function()
save(player, nil, true)
leftPlayers = leftPlayers - 1
if leftPlayers == 0 then
wait(2) -- Allow some time for the last save to complete
game:Shutdown()
end
end)()
end
end
end
for _, player in ipairs(Players:GetPlayers()) do
coroutine.wrap(setUp)(player)
end
Players.PlayerAdded:Connect(setUp)
Players.PlayerRemoving:Connect(save)
game:BindToClose(onShutdown)
while true do
wait(60)
for _, player in ipairs(Players:GetPlayers()) do
coroutine.wrap(save)(player, true)
end
end
And here is the pack/unpack module that this Datastore uses:
local module = {}
module.unpack = function(parent, children)
if not parent or not parent:IsA("Instance") then
return
end
for i, child in ipairs(children) do
local new
if child.folder_name then
new = Instance.new("Folder")
new.Name = child.folder_name
elseif child.int_name then
new = Instance.new("IntValue")
new.Name = child.int_name
elseif child.bool_name then
new = Instance.new("BoolValue")
new.Name = child.bool_name
elseif child.string_name then
new = Instance.new("StringValue")
new.Name = child.string_name
end
if not new:IsA("Folder") and child.value then
new.Value = child.value
end
new.Parent = parent
if child.children then
module.unpack(new, child.children)
end
end
end
module.pack = function(instance, Table)
Table = Table or {} -- Initialize Table as an empty table if not provided
local new_table = {}
if instance:IsA("Folder") then
new_table["folder_name"] = instance.Name
elseif instance:IsA("IntValue") then
new_table["int_name"] = instance.Name
elseif instance:IsA("BoolValue") then
new_table["bool_name"] = instance.Name
elseif instance:IsA("StringValue") then
new_table["string_name"] = instance.Name
end
if not instance:IsA("Folder") then
new_table["value"] = instance.Value
end
if #instance:GetChildren() > 0 then
local children_table = {}
new_table["children"] = children_table
for i, child in ipairs(instance:GetChildren()) do
module.pack(child, children_table)
end
end
table.insert(Table, new_table)
return Table
end
return module
Thank you for taking the time to review my code and provide any assistance or insights you may have!