UpdateAsync() does not seem to work

Hello! :wave:

I recently heard that using UpdateAsync() is a much better function than SetAsync(), as it prevents the player’s from going back to 0 when a data loss occurs and just restores the data he had before the wipe.

I tried to use UpdateAsync() in my script but it does not seem to work. Seeing the script wouldn’t show me any errors I decided to add a webhook incase and this is what I get when I use UpdateAsync().

https://cdn.discordapp.com/attachments/902011041641287710/926479912242647090/unknown.png

And this is what I get when I use SetAsync().

https://cdn.discordapp.com/attachments/902011041641287710/926480073895313408/unknown.png

I tried going on the DevHub and the Ressources page but I didn’t really understand clearly what was the difference and why my script would break. Could anyone help me out? Here is the part of the script where the script detects the player leaving.

game.Players.PlayerRemoving:Connect(function(player)
	
	local playerstats = leaderstatscreatetable(player)
	local moreplayerdatastats = moreplrcreatetable(player)
	local weaponsdata = weaponscreatetable(player)
	local skinsdata = skinscreatetable(player)
	local playerUserId = "Player_"..player.UserId
	local webhook = "https://discord.com/api/webhooks/webhooklinkhere"
	local httpservice = game:GetService("HttpService")
	
	local success, err = pcall(function()
		plrData:UpdateAsync(playerUserId, playerstats)
		morePlrData:UpdateAsync(playerUserId, moreplayerdatastats)
		weaponData:UpdateAsync(playerUserId, weaponsdata)
		skinData:UpdateAsync(playerUserId, skinsdata)
		local data = { content = "The player "..player.Name.. "(".. player.UserId ..")".. " successfully saved his data upon leaving." }
		httpservice:PostAsync(webhook, httpservice:JSONEncode(data))
	end)
	if not success then
		local data = { content = "The player "..player.Name.. "(".. player.UserId ..")".. " couldn't save his data upon leaving." }
		httpservice:PostAsync(webhook, httpservice:JSONEncode(data))
	end
end)

(Sorry for the possible grammar faults and wacky structures of the phrases, I still have to get used to the DevForum.)

in your functions, did you define what data to be updated? In example:

local NewData = player.Kills.Value
function dosomething(OldData) OldData = NewData return NewData end

DataStore:UpdateAsync(Key, dosomething)

When I call the function UpdateAsync(), I include the player’s UserId (which has been set above) and I include a table in which is stored all the IntValues and such’s names and values, if that answers your question.

Here is a local function I created to create the table:

local function leaderstatscreatetable(player)
	local player_stats = {}
	for _, stat in pairs(player:WaitForChild("leaderstats"):GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

I wouldn’t post your Discord webhook here in case people have malicious intentions. Also, Discord has blocked Roblox servers from sending webhook requests.

1 Like

Thank you for letting me aware.

I first thought that there may be an issue if I publicly give out the webhook.

I can still receive webhook requests from the bot whenever I send one through a script. Maybe it only works in Studio?

Oh, have you potentially tried storing all the data under the same key? @Den_S (Legendary creator of Theme Park Tycoon 2) recommends to never use SetAsync unless you are absolutely certain there is no data related to that key. You are calling UpdateAsync(), a yielding function for many keys at once when you can store all the data in those keys into a dictionary whose key would be the name the name of whatever data you store and the value the data. I won’t write the code for you and I do not recommend others to too since thats no way of learning. Let us know if there is any other issues. Keep Coding!

I believe it only works in studio yes as I used it for exploit logs and it was firing in studio yet in-game was error 403 (no access) if I remember correctly

I see.

So you are telling me I should store all the tables into one dictionary and then call the UpdateAsync() function?

Sorry if my understanding of the subject might be limited, DataStoreService is just a subject that really gives me headaches when I try to debunk it.

yeah, always wrap those functions in pcalls to catch errors.

Alright.

I’ll just keep it as a debug when I use Studio.

Alrighty. I’ll try to do that.

yes! Limits calling UpdateAsync constantly, it goes like:

:UpdateAsync(playerUserId, function(OldData) OldData = {playerstats = player_stats, moredatastats = "whatever data youve assigned",}

I’m back after around 20 minutes of working around.

When I use your method, the script automatically adds an end) (probably because of the function)
What should I do?

plrData:UpdateAsync(playerUserId, function(OldData) OldData = {plrData = playerstats, morePlrData = moreplayerdatastats, weaponData = weaponsdata, skinData = skinsdata}
	print("work?")
end)

Additional details, it printed the “work?”, but it does not actually save the data. Here is the full script if you need.

--[[ DATASTORESERVICE VALUES
]]--

-- DATA VERSIONS: 0 = pre-alpha / 1 = alpha release / 2 = beta release / 3 = main release / 4-idk = if data reset is needed

local DS = game:GetService("DataStoreService")
local plrVersion = script:WaitForChild("PlrDataVersion").Value
local moreplrVersion = script:WaitForChild("MorePlrDataVersion").Value
local weaponVersion = script:WaitForChild("WeaponDataVersion").Value
local skinVersion = script:WaitForChild("SkinDataVersion").Value
local plrData = DS:GetDataStore("PlayerData"..plrVersion)
local morePlrData = DS:GetDataStore("MorePlayerData"..moreplrVersion)
local weaponData = DS:GetDataStore("WeaponData"..weaponVersion)
local skinData = DS:GetDataStore("SkinData"..skinVersion)

game.Players.PlayerAdded:Connect(function(player)
	
	--folders
	
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"
	
	local datafolder = Instance.new("Folder", player)
	datafolder.Name = "Data"
	
	local skinf = Instance.new("Folder", datafolder)
	skinf.Name = "Skins"
	
	local weaponf = Instance.new("Folder", datafolder)
	weaponf.Name = "Unlocked"
	
	local moredataFolder = Instance.new("Folder", player)
	moredataFolder.Name = "MoreData"
	
	-- leaderstats values
	
	local lvl = Instance.new("IntValue", leaderstats)
	lvl.Name = "Level"
	
	local exp = Instance.new("IntValue", leaderstats)
	exp.Name = "EXP"
	
	local gold = Instance.new("IntValue", leaderstats)
	gold.Name = "Gold"
	
	-- more plr values
	
	local ban = Instance.new("BoolValue", moredataFolder)
	ban.Name = "Banned"
	
	local winstreak = Instance.new("IntValue", moredataFolder)
	winstreak.Name = "WinStreak"

	local storyval = Instance.new("StringValue", moredataFolder)
	storyval.Name = "StorylineStatus"
	
	-- weapons values
	
	local realknife = Instance.new("BoolValue", weaponf)
	realknife.Name = "Real Knife"

	local scythe = Instance.new("BoolValue", weaponf)
	scythe.Name = "Scythe"

	local emptygun = Instance.new("BoolValue", weaponf)
	emptygun.Name = "Empty Gun"
	
	local pan = Instance.new("BoolValue", weaponf)
	pan.Name = "Frying Pan"
	
	local gloves = Instance.new("BoolValue", weaponf)
	gloves.Name = "Tough Gloves"
	
	-- skins values
	
	local giornoskin = Instance.new("BoolValue", skinf)
	giornoskin.Name = "GiornoSans"

	local fanonskin = Instance.new("BoolValue", skinf)
	fanonskin.Name = "FanonSans"

	local casinoskin = Instance.new("BoolValue", skinf)
	casinoskin.Name = "CasinoSans"

	local dripskin = Instance.new("BoolValue", skinf)
	dripskin.Name = "DripSans"
	
	local jojoskin = Instance.new("BoolValue", skinf)
	jojoskin.Name = "JotaroSans"

	local noobskin = Instance.new("BoolValue", skinf)
	noobskin.Name = "NoobSans"

	local santasans = Instance.new("BoolValue", skinf)
	santasans.Name = "SantaSans"
	
	local lowlvlskin = Instance.new("BoolValue", skinf)
	lowlvlskin.Name = "LowLevelDust"
	
	-- temporary values
	
	local afk = Instance.new("BoolValue", player)
	afk.Name = "IsAFK"
	afk.Value = false

	local monster348 = Instance.new("StringValue", player)
	monster348.Name = "MonsterType"
	monster348.Value = "Sans"

	local XDD = Instance.new("BoolValue", player)
	XDD.Name = "AlreadyVoted"
	XDD.Value = false

	local ilanisanoob = Instance.new("BoolValue", player)
	ilanisanoob.Name = "MorphPreference"
	ilanisanoob.Value = true

	local monster68 = Instance.new("BoolValue", player)
	monster68.Name = "MousePreference"
	monster68.Value = true

	local monster88 = Instance.new("BoolValue", player)
	monster88.Name = "CanGetKR"
	monster88.Value = true

	local monster77 = Instance.new("BoolValue", player)
	monster77.Name = "CanGetParalyzed"
	monster77.Value = true

	local monster9 = Instance.new("BoolValue", player)
	monster9.Name = "CanGetBLEED"
	monster9.Value = true

	local we = Instance.new("StringValue", player)
	we.Name = "SelectedWeapon"
	we.Value = "Toy Knife"

	local ss = Instance.new("StringValue", player)
	ss.Name = "SelectedSoul"
	ss.Value = "Basic"
	
	local selectedskin = Instance.new("StringValue", player)
	selectedskin.Name = "SelectedSkin"
	selectedskin.Value = ""
	
	-- leaderstats values set

	local playerUserId = "Player_"..player.UserId
	local plrdatavalues = plrData:GetAsync(playerUserId)
	if plrdatavalues then
		lvl.Value = plrdatavalues["Level"]
		exp.Value = plrdatavalues["EXP"]
		gold.Value = plrdatavalues["Gold"]
	else
		lvl.Value = 1
		exp.Value = 0
		gold.Value = 0
	end
	
	-- more plr values set
	
	local moreplrdatavalues = morePlrData:GetAsync(playerUserId)
	if moreplrdatavalues then
		ban.Value = moreplrdatavalues["Banned"]
		winstreak.Value = moreplrdatavalues["WinStreak"]
		storyval.Value = moreplrdatavalues["StorylineStatus"]
	else
		ban.Value = false
		winstreak.Value = 0
		storyval.Value = "Begin"
	end
	
	-- weapons values set
	
	local weapondatavalues = weaponData:GetAsync(playerUserId)
	if weapondatavalues then
		realknife.Value = weapondatavalues["Real Knife"]
		scythe.Value = weapondatavalues["Scythe"]
		emptygun.Value = weapondatavalues["Empty Gun"]
		pan.Value = weapondatavalues["Frying Pan"]
		gloves.Value = weapondatavalues["Tough Gloves"]
	else
		realknife.Value = false
		scythe.Value = false
		emptygun.Value = false
		pan.Value = false
		gloves.Value = false
	end
	
	-- skins values set
	
	local skindatavalues = skinData:GetAsync(playerUserId)
	if skindatavalues then
		giornoskin.Value = skindatavalues["GiornoSans"]
		fanonskin.Value = skindatavalues["FanonSans"]
		casinoskin.Value = skindatavalues["CasinoSans"]
		dripskin.Value = skindatavalues["DripSans"]
		noobskin.Value = skindatavalues["NoobSans"]
		santasans.Value = skindatavalues["SantaSans"]
		lowlvlskin.Value = skindatavalues["LowLevelDust"]
		jojoskin.Value = skindatavalues["JotaroSans"]
	else
		giornoskin.Value = false
		fanonskin.Value = false
		casinoskin.Value = false
		dripskin.Value = false
		noobskin.Value = false
		santasans.Value = false
		lowlvlskin.Value = false
		jojoskin.Value = false
	end
end)

local function leaderstatscreatetable(player)
	local player_stats = {}
	for _, stat in pairs(player:WaitForChild("leaderstats"):GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

local function weaponscreatetable(player)
	local player_stats = {}
	for _, stat in pairs(player:WaitForChild("Data").Unlocked:GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

local function skinscreatetable(player)
	local player_stats = {}
	for _, stat in pairs(player:WaitForChild("Data").Skins:GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

local function moreplrcreatetable(player)
	local player_stats = {}
	for _, stat in pairs(player:WaitForChild("MoreData"):GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

game.Players.PlayerRemoving:Connect(function(player)
	
	local playerstats = leaderstatscreatetable(player)
	local moreplayerdatastats = moreplrcreatetable(player)
	local weaponsdata = weaponscreatetable(player)
	local skinsdata = skinscreatetable(player)
	local playerUserId = "Player_"..player.UserId
	local webhook = "https://discord.com/api/webhooks/"
	local httpservice = game:GetService("HttpService")
	
	plrData:UpdateAsync(playerUserId, function(OldData) OldData = {plrData = playerstats, morePlrData = moreplayerdatastats, weaponData = weaponsdata, skinData = skinsdata}
		print("work?")
	end)
	
	--[[ local success, updatedName, keyInfo = pcall(function()
		return plrData:UpdateAsync(playerUserId, leaderstatscreatetable)
	end)
	if success then
		print("work")
	else
		print("bruh")
	end ]]--
	
	--[[ local success, err = pcall(function()
		plrData:SetAsync(playerUserId, playerstats)
		morePlrData:SetAsync(playerUserId, moreplayerdatastats)
		weaponData:SetAsync(playerUserId, weaponsdata)
		skinData:SetAsync(playerUserId, skinsdata)
		local data = { content = "The player "..player.Name.. "(".. player.UserId ..")".. " successfully saved his data upon leaving." }
		httpservice:PostAsync(webhook, httpservice:JSONEncode(data))
	end)
	if not success then
		local data = { content = "The player "..player.Name.. "(".. player.UserId ..")".. " couldn't save his data upon leaving." }
		httpservice:PostAsync(webhook, httpservice:JSONEncode(data))
	end ]]--
end)

--[[ local playerstats = leaderstatscreatetable(player)
local success, err = pcall(function()
	local playerUserId = "Player_" .. player.UserId
	plrData:SetAsync(playerUserId, playerstats)
end)
if not success then
	local webhook = "https://discord.com/api/webhooks/"
	local httpservice = game:GetService("HttpService")
	local data = { content = "The player "..player.Name.. "(".. player.UserId ..")".. " couldn't save his leaderstats data upon leaving." }
	httpservice:PostAsync(webhook, httpservice:JSONEncode(data))
end

-- more data set

local moreplayerdatastats = moreplrcreatetable(player)
local success, err = pcall(function()
	local playerUserId = "Player_" .. player.UserId
	plrData:SetAsync(playerUserId, moreplayerdatastats)
end)
if not success then
	local webhook = "https://discord.com/api/webhooks/"
	local httpservice = game:GetService("HttpService")
	local data = { content = "The player "..player.Name.. "(".. player.UserId ..")".. " couldn't save his player data data upon leaving." }
	httpservice:PostAsync(webhook, httpservice:JSONEncode(data))
end

-- weapons set

local weaponsdata = weaponscreatetable(player)
local success, err = pcall(function()
	local playerUserId = "Player_" .. player.UserId
	plrData:SetAsync(playerUserId, weaponsdata)
end)
if not success then
	local webhook = "https://discord.com/api/webhooks/webhook"
	local httpservice = game:GetService("HttpService")
	local data = { content = "The player "..player.Name.. "(".. player.UserId ..")".. " couldn't save his weapon data upon leaving." }
	httpservice:PostAsync(webhook, httpservice:JSONEncode(data))
end

-- skins set

local skinsdata = skinscreatetable(player)
local success, err = pcall(function()
	local playerUserId = "Player_" .. player.UserId
	plrData:SetAsync(playerUserId, skinsdata)
end)
if not success then
	local webhook = "https://discord.com/api/webhooks/webhookstuff"
	local httpservice = game:GetService("HttpService")
	local data = { content = "The player "..player.Name.. "(".. player.UserId ..")".. " couldn't save his skins data upon leaving." }
	httpservice:PostAsync(webhook, httpservice:JSONEncode(data))
end ]]-- 

Update async has a function argument, you wanna read the updateasync tutorial again.

You’re doing it very wrong.

can you run this in the command bar and show me the result in the output? should show if there actually is saved data to the key

warn(game.HttpService:JSONEncode(game.DataStoreService:GetDataStore(“PlayerData0”):GetAsync(“Player_1538726451”)))

This is what is printed whenever I run your command.

(Once again, I excuse myself if this gets annoying, I just does not understand DataStore at all.)

oh yeah completly forgot roblox formatting

run warn(game.HttpService:JSONEncode(game.DataStoreService:GetDataStore(“PlayerData0”):GetAsync(“Player_1538726451”)))

or replace the respective symbols " and () and . with their respective buttons on the keyboard and rerun it

I think you forgot to add :GetService() ?

game:GetService("DataStoreService")

This is what I get. Seems like it works fine.

im using game.DataStoreService just for the command since its quicker to write, some services can be retrieved directly other, you need to call GetService on

1 Like