Need help with shop/currency datasave

Do you have a player leaving event or bind to close?
Sorry this doesn’t matter since it updates your data when money changes. May I ask are you changing the money on the client side, if so I don’t think the Changed Event would run.

DataStores can only be accessed from a server script, make sure it’s placed inside ServerScriptService.

Im pretty sure It is server side

It is, is there something I need to add to my data store script??

Is the sell button being clicked on the client and then sent to the server to check?

local datastore = game:GetService("DataStoreService")
local ds1 = datastore:GetDataStore("MoneySaveSystem")

game.Players.PlayerAdded:connect(function(plr)
	local folder = Instance.new("Folder")
	folder.Parent = plr
	folder.Name = "leaderstats"
	local money = Instance.new("IntValue")
	money.Parent = folder
	money.Name = "Money"
	money.Value = 0
	money.Value = ds1:GetAsync(plr.UserId)
	ds1:SetAsync(plr.UserId, money.Value)
	money.Changed:connect(function()
		ds1:SetAsync(plr.UserId, money.Value)
	end)
end)

No offence but nothing has really changed in this script.

Edit: Yes you should parent it after but the values are still being parented so I don’t believe that is the issue here

None taken, there’s not much to change.

This is the script that is inside of the buy button if that answers any questions

local item = script.Parent
local Shoes = script.Parent.Parent.Parent.Frame1.Shoes  
local value = 40000 

item.MouseButton1Click:Connect(function()
	if game.Players.LocalPlayer.leaderstats.Money.Value >= value then
		game.Players.LocalPlayer.leaderstats.Money.Value = game.Players.LocalPlayer.leaderstats.Money.Value - value
		item.Text = "purchased"
		Shoes.Visible = true
		value = 0
		
	else
		item.Text = "not purchased"
		wait(1)
		item.Text = "Purchase"
	
			value = 0
			Shoes.Visible = true
		end
		
	
end)





Why would you save the money every time the money changes? It’s going to request too much saving and it will overflow and exceed the limit. You should only save the data when the player leaves, and you should wrap the calls in pcall() function.

There’s the issue, it is being handled on the client. Make sure to use remote events to communicate to the server.

so the datastore is not the issue?

Depends on how frequently money is earned. You can write to a DataStore with a single key once every 6 seconds.

The data store is still an issue. Please read my reply first.

No the only issue I see is that a lot of requests will be sent since currency changes quite often, also using pcalls like stated by @ItzMeZeus_IGotHacked

Make sure to use remote events since anything can happen on the client, like the client can give themselves money and if its being handled client side then the server would never know what’s going on.

Little tutorial

Make a remote event in ReplicatedStorage and call it Sell or something better.

-- Server Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SellEvent = ReplicatedStorage:WaitForChild("Sell") -- I add :WaitForChild just in case

SellEvent.OnServerEvent:Connect(function(player) -- Player is defined as the first parameter always I believe
   if player:IsDecendantOf(Players) and player.leaderstats.Money.Value >= ? then -- If needed add more checks
    -- Do whatever you need here
   end
end

Now the client side is similar and much more simple

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SellEvent = ReplicatedStorage:WaitForChild("Sell") 

-- Clicked Event
SellEvent:FireServer() -- This is how you send a event to server
1 Like

Ok so it wont save because I need to use events?

And I need to fix the datastore so It saves less like someone said above?

You have to do the operation on the server.

Not saves less, but save in a safer way.

– LOCAL SCRIPT –

local repstorage = game:GetService("ReplicatedStorage")
local buyevent = repstorage:WaitForChild("BuyEvent")
local item = script.Parent
local shoes = script.Parent.Parent.Parent.Frame1.Shoes
local value = 40000
local players = game:GetService("Players")
local player = players.Player or players.PlayerAdded:wait()

item.MouseButton1Click:Connect(function()
	if player:WaitForChild("leaderstats"):WaitForChild("Money").Value >= value then
		buyevent:FireServer(value)
		item.Text = "purchased"
		shoes.Visible = true
		value = 0
	else
		item.Text = "not purchased"
		wait(1)
		item.Text = "Purchase"
		value = 0
		shoes.Visible = true
	end
end)

– SERVER SCRIPT –

local datastore = game:GetService("DataStoreService")
local ds1 = datastore:GetDataStore("MoneySaveSystem")
local repstorage = game:GetService("ReplicatedStorage")
local buyevent = repstorage:WaitForChild("BuyEvent")
local players = game:GetService("Players")

players.PlayerAdded:connect(function(plr)
	local folder = Instance.new("Folder")
	folder.Parent = plr
	folder.Name = "leaderstats"
	local money = Instance.new("IntValue")
	money.Parent = folder
	money.Name = "Money"
	money.Value = 0
	money.Value = ds1:GetAsync(plr.UserId)
	ds1:SetAsync(plr.UserId, money.Value)
	money.Changed:connect(function()
		ds1:SetAsync(plr.UserId, money.Value)
	end)
end)

buyevent.OnServerEvent:Connect(function(player, value)
	player:WaitForChild("leaderstats"):WaitForChild("Money").Value -= value
end)

Make a RemoteEvent instance named “BuyEvent” and place it inside the ReplicatedStorage folder, place the server script inside ServerScriptService folder & place the local script wherever it was placed before inside the ScreenGui.

I would recommend saving a table instead of each individual data like this

local DataTable = {
    Money = 0,
    Inventory = {},
    -- Any other values
}

Then all you would have to do is save the table and it’s easier to manage. Hope that helps

You can’t store a table value inside a DataStore, just a warning.