GUI Shop help needed

I need help finishing my ui shop. The ui is done but some of the scripting needs help :frowning:

Buying on the server side. Events get called alot per second even though theres a check so it dosnt, and it dosnt save like its sopused to (I think it has something to do with the table not updating)

local data = inventoryData:GetAsync("OwnedSloths-" .. player.UserId)
	if not buyingBounce then
		buyingBounce = true
		local ItemName = ItemList.Name
		local ItemCost = ItemList.Cost
		if coins:GetAsync("Coins_Save-" .. player.UserId) >= tonumber(ItemCost) then
			player.leaderstats.Coins.Value -= ItemCost
			table.insert(data.Owned, tostring(ItemName))
			inventoryData:SetAsync("OwnedSlots-" .. player.UserId, data)
			buyingBounce = false
			return data
		else
			buyingBounce = false
			return false
		end
	end

Please get back soon. Thanks in advance!

2 Likes

I think it has to do with your Debounce. All possible outcomes of your if and else statement loops the code. Also, the return in your else statement returns what exactly? there is no variable or function with false. Unless it’s referenced somewhere and not in the given code.

This is just a guess. Might work?

1 Like

I added the Debounce cause people might spam the button. Again it has somthing to do with the data not saving correctly

Not sure if this would solve your problem, but I notice you are writing and reading from the data stores each time it is prompted. Typically in my games, I store a global (_G.Variable) table on the server, which contains all the players’ data. Rather than reading and writing over and over, it loads upon join, and saves when a player leaves. There is auto saving every so often as well.

2 Likes

No im not using this. Right now im using normal datastores and when a player buys somthing, it loads the data into a list, then adds the item there buying to it, then sends it off to be saved

Yes, that is why I suggest a global table storing data. Each time you write and read from data store, it takes up space on the server. Reducing the amount of times you do this will improve your game’s functionality and speed. Overall, it reduces exhaustion of the roblox servers.

1 Like

How would I implement this into my game?

I always start a Database script with:

_G.PlayerData = {}

Upon joining, a function is called on the player which creates a data table for them.

function CreateData(Player)
     local NewData = {
          Inventory = {},
          Coins = 50,
     }

     local SaveData

     pcall(function()
          SaveData = DataStore:GetAsync(Player.UserId)
     end)

     if SaveData then
          NewData = SaveData
     end

     _G.PlayerData[Player.UserId] = NewData
end

That is the basis of the data creation function. It creates a default data table, and overwrites it if they have already saved data previously.

I typically put a while loop at the very end of the function that waits every 1.5-2 minutes or so, and saves the data to the datastore. But only if the data has changed. I also sometimes include a BindableEvent inside the data table which can be fired when data is changed. It will then change a variable that tells whether it should be saved or not. Basically meaning if anything in the data is changed.

When a player leaves, it saves the data, removes the data from the _G table, and then that’s it!

Hope this helps.

  • MattPrograms
1 Like

Couldnt any exploiter come and just read the variable and make changes to it? Or can it not be changed by local script?

Local scripts can’t change server scripts. If it is in server script service, they can’t access the table at all. You will need to replicate the data to each client, but they can’t directly alter it unless you have a poor technique.

1 Like

Can you tell me what script I should put each code it? Like the _G part should go in a module script? And how will I go about saving it?

All of that would be in a ServerScript (Script instance). Saving it will just be the same as typical data saving. When a player leaves, access their data through:

_G.PlayerData[Player.UserId]

And save it to the data store, through:

DataStore:SetAsync(Player.UserId,Data)
1 Like

so i just change

_G.PlayerData

in a server script when ever the player buys or needs to change somthing?

Make sure you alter that player’s data in particular. But yes.

1 Like

Sorry that im asking this so late, but how do I detect when the coins value changes? I have implemented this into my game but I cant update the leaderstats

Coins = 500; --Detect when that changes
Inventory = {};

So like I said in a previous reply, I use a BindableEvent Instance to fire when data is changed. Setup the auto saving function to only save if the data has changed.

UpdateData = Instance.new("BindableEvent")

Using this method you would have to alter the data table.

NewData = {
     Data = {
          Coins = 500;
          Inventory = {};
     }
     
     UpdateData = Instance.new("BindableEvent")
}

Whenever changing the coins or inventory value, fire the update data event. Have to script detect when that event is fired, and set a variable to true.

local NeedsSaving = false

NewData.UpdateData.Event:Connect(function()
     NeedsSaving = true
end)

-- and then on the save function do something like this:

local function SaveData()
     if NeedsSaving then
          DataStore:SetAsync(UserId,NewData.Data)
     end
end

I am sure you can figure the rest out.