Why perks not saving, i tried 100 times to rewrite script but not working

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local HttpService = game:GetService("HttpService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local perksStore = DataStoreService:GetDataStore("PerksStore")

local PerksEvent = ReplicatedStorage:FindFirstChild("PerksEvent")

local defaultData = {
	owned = {},
	equipped = {},
	points = 0,
}
local function saveData(player, data)
	if not data then
		warn("not saved", player.Name)
		return
	end
	print("saving:", player.Name, data)
	local success, err = pcall(function()
		perksStore:SetAsync("perks_"..player.UserId, data)
	end)
	print("Saved:", success, err)
end

local function loadData(player)
	print("loading data", player.Name)
	local data
	local success, err = pcall(function()
		data = perksStore:GetAsync("perks_"..player.UserId)
	end)
	print("results lol", success, err, data)

	if success and data then
		return data
	else
		return table.clone(defaultData)
	end
end

Players.PlayerAdded:Connect(function(player)
	local data = loadData(player)

	local json = HttpService:JSONEncode(data)
	player:SetAttribute("PerksData", json)

	PerksEvent:FireClient(player, data)
end)

Players.PlayerRemoving:Connect(function(player)
	local str = player:GetAttribute("PerksData")
	if str then
		local data = HttpService:JSONDecode(str)
		saveData(player, data)
	end
end)

game:BindToClose(function()
	for _, player in ipairs(Players:GetPlayers()) do
		local str = player:GetAttribute("PerksData")
		if str then
			local data = HttpService:JSONDecode(str)
			saveData(player, data)
		end
	end
end)

PerksEvent.OnServerEvent:Connect(function(player, action, perkName)
	local str = player:GetAttribute("PerksData")
	if not str then return end

	local data = HttpService:JSONDecode(str)

	if action == "Buy" then
		if data.points > 0 and not table.find(data.owned, perkName) then
			table.insert(data.owned, perkName)
			data.points -= 1
		end

	elseif action == "Equip" then
		if table.find(data.owned, perkName) and not table.find(data.equipped, perkName) then
			table.insert(data.equipped, perkName)
		end

	elseif action == "Unequip" then
		for i, v in ipairs(data.equipped) do
			if v == perkName then
				table.remove(data.equipped, i)
				break
			end
		end

	elseif action == "Request" then
		PerksEvent:FireClient(player, data)
		return
	end

	local json = HttpService:JSONEncode(data)
	player:SetAttribute("PerksData", json)
	saveData(player, data)

	PerksEvent:FireClient(player, data)
end)

Version two..

This may work for you
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local HttpService = game:GetService("HttpService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local perksStore = DataStoreService:GetDataStore("PerksStore")
local PerksEvent = ReplicatedStorage:WaitForChild("PerksEvent")

local defaultData = {owned = {}, equipped = {}, points = 0}
local db = {}

local function saveData(player, data)
	if not data then return end
	local key = "perks_"..player.UserId
	db[player.UserId] = true
	pcall(function()
		perksStore:UpdateAsync(key, function() return data end)
	end)
	db[player.UserId] = nil
end

local function loadData(player)
	local key = "perks_"..player.UserId
	local ok, data = pcall(function() return perksStore:GetAsync(key) end)
	return (ok and data) or table.clone(defaultData)
end

Players.PlayerAdded:Connect(function(player)
	local data = loadData(player)
	player:SetAttribute("PerksData", HttpService:JSONEncode(data))
	PerksEvent:FireClient(player, data)
end)

Players.PlayerRemoving:Connect(function(player)
	local str = player:GetAttribute("PerksData")
	if str then
		saveData(player, HttpService:JSONDecode(str))
	else
		saveData(player, loadData(player))
	end
end)

game:BindToClose(function()
	for _, player in ipairs(Players:GetPlayers()) do
		local str = player:GetAttribute("PerksData")
		if str then
			saveData(player, HttpService:JSONDecode(str))
		else
			saveData(player, loadData(player))
		end
	end
end)

PerksEvent.OnServerEvent:Connect(function(player, action, perkName)
	local str = player:GetAttribute("PerksData")
	if not str then return end
	local data = HttpService:JSONDecode(str)

	if action == "Buy" then
		if data.points > 0 and not table.find(data.owned, perkName) then
			table.insert(data.owned, perkName)
			data.points -= 1
		end
	elseif action == "Equip" then
		if table.find(data.owned, perkName) and not table.find(data.equipped, perkName) then
			table.insert(data.equipped, perkName)
		end
	elseif action == "Unequip" then
		for i, v in ipairs(data.equipped) do
			if v == perkName then
				table.remove(data.equipped, i)
				break
			end
		end
	elseif action == "Request" then
		PerksEvent:FireClient(player, data)
		return
	end

	player:SetAttribute("PerksData", HttpService:JSONEncode(data))
	if not db[player.UserId] then saveData(player, data) end
	PerksEvent:FireClient(player, data)
end)

Slight modification.. Make sure nothing is trying to save nil. Print check that.

This is forums scripting help.. Post something constructive or not at all..

1 Like

Still not saving perks when i buy

Is API access is enabled, so it can work with the datastore?

Because Attributes can’t store tables idk friend told me

yes, i turn on api access in settings

soo what right now, i can’t stil solve problem

I’m updating my post for before ^ as we go.. Hard to get these perfect unless I totally recreate it.
I don’t want to leave something that isn’t working however..

I’m going to PM you one of my more complicated scripts working with what you’re doing here.
It’s not just what you’re doing, but it is working with JSON and the datastore.

Hope that is enough information to help you out.. good luck!

Debug the attribute and see if its correct, they might have string limit

1 Like