What do you want to achieve? Optimizing my datastores, from SetAsync() to UpdateAsync()
What is the issue? kept getting this error: ServerScriptService.PlayerDataHandler.PlayerSettings.PlayerSettingsHandler:51: table index is nil
What solutions have you tried so far? I found some similar issues of mine but, i don’t know why but i don’t get it
here is the lines of code that updates the player data when it leaves
local function createTable(player)
local datafolder = player:WaitForChild("PlayerDataFolder")
local playersettings = datafolder:WaitForChild("PlayerSettings")
local playersettingsdatatable = {}
for i, value in pairs(playersettings:GetChildren()) do
playersettingsdatatable[value.Name] = value.Value
end
return playersettingsdatatable
end
game.Players.PlayerRemoving:Connect(function(player)
local playersettingsdatatable = createTable(player)
local success, err = pcall(function()
local userId = player.UserId
playersettingsdata:UpdateAsync(userId, function(oldData)
local dataTable = oldData or {}
for i, item in pairs(playersettingsdatatable) do
if item then
dataTable[item.Name] = item.Value
end
end
return dataTable
end)
end)
if success then
print(player.Name .. "'s data successfully saved (settings)")
else
warn(player.Name .."'s data cant be found (settings)... cause: " .. err)
end
end)
and here’s the entire code…
local datastoreservice = game:GetService("DataStoreService")
local playersettingsdata = datastoreservice:GetDataStore("PlayerSettingsDataStore")
game.Players.PlayerAdded:Connect(function(player)
local datafolder = player:WaitForChild("PlayerDataFolder")
local userId = player.UserId
local playerSettings = Instance.new("Folder")
playerSettings.Name = "PlayerSettings"
playerSettings.Parent = datafolder
local playerDisplayName = Instance.new("StringValue")
playerDisplayName.Name = "PlayerDisplayName"
playerDisplayName.Parent = playerSettings
local data
local success, err = pcall(function()
data = playersettingsdata:GetAsync(userId)
end)
if data then
playerDisplayName.Value = data["PlayerDisplayName"]
else
playerDisplayName.Value = player.Name
end
end)
local function createTable(player)
local datafolder = player:WaitForChild("PlayerDataFolder")
local playersettings = datafolder:WaitForChild("PlayerSettings")
local playersettingsdatatable = {}
for i, value in pairs(playersettings:GetChildren()) do
playersettingsdatatable[value.Name] = value.Value
end
return playersettingsdatatable
end
game.Players.PlayerRemoving:Connect(function(player)
local playersettingsdatatable = createTable(player)
local success, err = pcall(function()
local userId = player.UserId
playersettingsdata:UpdateAsync(userId, function(oldData)
local dataTable = oldData or {}
for i, item in pairs(playersettingsdatatable) do
if item then
dataTable[item.Name] = item.Value
end
end
return dataTable
end)
end)
if success then
print(player.Name .. "'s data successfully saved (settings)")
else
warn(player.Name .."'s data cant be found (settings)... cause: " .. err)
end
end)
game:BindToClose(function()
for i, player in pairs(game.Players:GetPlayers()) do
if player then
player:Kick("Shutting down - Please rejoin, ariga2!")
end
end
wait(5)
end)
im still optimizing the scripts as much as i can before working on the other features… suggestions will help a lot
local function PRINTMEH(player)
local datafolder = player:WaitForChild("PlayerDataFolder")
local playerSettings = datafolder:WaitForChild("PlayerSettings")
for i, item in pairs(playerSettings:GetChildren()) do
print(item.Name .. " Value: ".. item.Value)
end
end
game.ReplicatedStorage.DEBUGREMOTE.OnServerEvent:Connect(PRINTMEH)
local script:
local UIS = game:GetService("UserInputService")
UIS.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.L then
game.ReplicatedStorage.DEBUGREMOTE:FireServer()
end
end)
I don’t know where line 51 was so it was a bit of a nightmare to scroll through your code to find the exact part that’s throwing an error. Please make sure to add comments in your code for support threads indicating where the source of the problem is just so it’s easier to navigate.
In any case, from what I’ve gone over it looks like you slightly misunderstand your own code. Your create table function creates a dictionary where the index is your setting and the value is of course the value of that ValueObject. Your createTable function will return a structure like this:
{
["foobar"] = "Hello world"
}
This dictionary does not have a name or key property though you attempt to access them in the transform function given to UpdateAsync. Recall that a for loop will iterate through key-value pairs in a table, the respective variables representing the key and the value. You already have access to both the name and the value, so you shouldn’t treat the table as though it didn’t serialise the ValueObjects.
Just make a change with your UpdateAsync’s for loop to use the index of the pair.
for key, value in pairs(playersettingsdatatable) do
dataTable[key] = value
end
Might I also suggest a different naming case, just on an unrelated note? Having your entire variable in flat case is kind of wonky to look at, but it’s fine if you can read it at least. I’d go with camelCase there as well as for a good number of your variables.
That’s not specific enough for me to know where you put it; I don’t know where you’re trying this. I’d like to reclarify that this is intended for the for loop in UpdateAsync, not createTable. The latter function in its original state takes care of serialising ValueObjects to a key-value paired dictionary. Please feel free to re-review my post for more information.
yeah thanks for it, i actually fixed it a while ago and here’s the final script:
local dataStore = game:GetService("DataStoreService")
local playerSettingsData = dataStore:GetDataStore("SettingsData")
local function playerAdded(player)
local dataFolder = player:WaitForChild("PlayerDataFolder")
local userId = player.UserId
local playerSettings = Instance.new("Folder")
playerSettings.Name = "PlayerSettings"
playerSettings.Parent = dataFolder
local playerDisplayName = Instance.new("StringValue")
playerDisplayName.Name = "PlayerDisplayName"
playerDisplayName.Parent = playerSettings
local data
local success, err = pcall(function()
data = playerSettingsData:GetAsync(userId .. "-Settings")
end)
if data then
print(player.Name .. "'s Settings has been loaded")
for i, item in pairs(playerSettings:GetChildren()) do
item.Value = data[item.Name]
end
else
print(player.Name .. "'s a new player.. or forgotten.. created a new Settings")
playerDisplayName.Value = player.Name
end
end
local function dataTable(player)
local dataFolder = player:WaitForChild("PlayerDataFolder")
local settingsFolder = dataFolder:WaitForChild("PlayerSettings")
local settingsTable = {}
for i, item in pairs(settingsFolder:GetChildren()) do
settingsTable[item.Name] = item.Value
end
return settingsTable
end
local function playerLeave(player)
local settingsTable = dataTable(player)
local userId = player.UserId
local success, err = pcall(function()
playerSettingsData:UpdateAsync(userId .. "-Settings", function(recentData)
local dataTable = recentData or {}
for item, value in pairs(settingsTable) do
dataTable[item] = value
end
return dataTable
end)
end)
if success then
print(player.Name .. "'s Settings saved!")
else
print(player.Name .. "'s Settings failed to save!, because ".. err)
end
end
game.Players.PlayerRemoving:Connect(playerLeave)
game.Players.PlayerAdded:Connect(playerAdded)