I’m trying to make a script that saves the player’s tools when added, and yesterday it was working perfectly fine. But I wanted to create a new one, so I changed the name and now I keep getting the same error, preventing me from even making the datastore work. I can’t change the name back either, and It’s stressing me out a ton. I’ve spent 7 hours trying to figure out what’s wrong, and nothings help. Someone please help me w this, thanks!
local DataStoreService = game:GetService('DataStoreService') or game:FindService('DataStoreService')
local Players = game:GetService("Players") or game:FindService("Players")
local Tools = game.ReplicatedStorage:WaitForChild("Tools")
do
local DS = DataStoreService:GetDataStore('PlrToolSaved')
local PlrToolSaves = {}
Players.PlayerAdded:Connect(function(plr)
repeat
task.wait()
until DataStoreService:GetRequestBudgetForRequestType(Enum.DataStoreRequestType.GetAsync) > 0
local Data = DS:GetAsync(plr.UserId)
if Data and typeof(Data) == 'table' then
PlrToolSaves[plr] = Data
else
PlrToolSaves[plr] = {}
end
local savedTool = Instance.new('Folder', plr)
savedTool.Name = 'AllToolSaved'
for _, v in ipairs(Data) do
Instance.new('Configuration', savedTool).Name = v
end
end)
Players.PlayerRemoving:Connect(function(plr)
local Data = PlrToolSaves[plr]
PlrToolSaves[plr] = nil
repeat
task.wait()
until DataStoreService:GetRequestBudgetForRequestType(Enum.DataStoreRequestType.SetIncrementAsync) > 0
DS:SetAsync(plr.UserId, Data)
end)
game:GetService('ReplicatedStorage').ShopBuy.OnServerEvent:Connect(function(player, tool, price)
if player.leaderstats.Points.Value >= price then
Instance.new('Configuration', player.AllToolSaved).Name = tool
player.leaderstats.Points.Value -= price
end
end)
end
The error is telling you that the argument for ipairs is invalid and it got nil (which means Data is nil, and that the player is new). Since you already have PlrToolSaves[plr] set to Data or an empty table if not found, you can simply replace Data here with PlrToolSaves[plr]
I have one question. I wanna make it so if you own a gamepass, and the tool has a certain name, it’ll add it to the table; If you don’t, then it won’t add it to the table.
game:GetService('ReplicatedStorage').ShopBuy.OnServerEvent:Connect(function(player, tool, price)
if player.leaderstats.Points.Value >= price then
Instance.new('Configuration', player.PlrToolSaved).Name = tool
player.leaderstats.Points.Value -= price
end
end)
end
I’ll detract from the post’s topic for a minute, just to improve on this further:
You don’t actually need to wait for the budget to be more than 0 to do anything.
Roblox’s limits are generous enough that you will not hit the queue limit if you are sending requests to datastores just once like in your code.
You should also wrap GetAsync() and SetAsync() in a pcall; as with most HTTP calls, they have a chance to drop and cause your script to error.
IntValues, StringValue, and in your case, ObjectValue are considered to be ValueObjects.
The way I see it, Configurations are just an archaic construct that developers can use to enable easily change settings for something, such as the stats of a weapon, etc.
It’s largely been superseded by Attributes though, and using ValueObjects also ensures type safety.
-- put this section at start of script
local MarketplaceService = game:GetService("MarketplaceService")
local GamepassId = 0 -- replace with your gamepass id
-------
game:GetService('ReplicatedStorage').ShopBuy.OnServerEvent:Connect(function(player, tool, price)
if player.leaderstats.Points.Value >= price then
Instance.new('Configuration', player.PlrToolSaved).Name = tool
player.leaderstats.Points.Value -= price
if tool = "the name of the specific tool" and MarketplaceService:UserOwnsGamepassAsync(player.UserId, gamepassId) then -- checks if player has gamepass with above id and matches the name you want
table.insert(PlrToolSaved[player],tool)
end
end
end)
end
I have one more request for help before I close this; How do I make it so it checks if you own, or have bought said gamepass, and if it checks that you own it when you join or when you bought it, it’ll add it to the Table.
But how do I make it so it doesn’t keep adding it to the table everytime you join.
Just use UserOwnsGamepassAsync like above everytime the player joins and if it returns true it adds to the table.
To check if the tool is in the table use table.find(PlrToolSaved[player], "name of tool") and add the tool to the table if it doesn’t return anything
Before I say anything, I’d say it’s probably because of this very common issue that’s easy to fix:
Data might not be saving in your game, because the server closes too fast, so data isn’t even able to save in the first place. You need a delay.
A quick fix is to tell the server to give a little delay before actually closing, to let data save. You can put this one line of code in a script, and it should do the job:
game:BindToClose(function() task.wait(5) end) --Delays 5 seconds before shutting down.
Or, you can literally do the data-saving process in that BindToClose function, so it does save the data, then close the game. Either way, it can work.
Now let’s see what’s actually going on-
One thing I’d do is put some print()s in a script and see where goes wrong. It helps you see where the script actually pauses, and to give you a better understanding of what is yielding the script in an infinite timelapse… or a little stupid typo in a variable. Try that out before doing anything else.