I have remade my saving system for my shop script, and for some reason this error appears:
Attempted to call require with invalid argument(s). - Server - ShopServer:7
I can’t really quite figure out what went wrong in the script… And I am fairly certain that error prevents me from buying things in the shop too.
Here’s my script
local conf = game.ReplicatedStorage:WaitForChild("Configuration")
local currencyName = conf:WaitForChild("CurrencyName")
local startingCurrency = conf:WaitForChild("StartingCurrency")
local canBuyMultipleTimes = conf:WaitForChild("CanBuyItemMultipleTimes")
local modules = script:WaitForChild("ModuleScripts")
local SavingData = require(game.ServerScriptService.SavingData)
local CreateLeaderstats = require(modules:WaitForChild("CreateLeaderstats"))
local CreateTools = require(modules:WaitForChild("CreateTools"))
local BuyTool = require(modules:WaitForChild("BuyTool"))
local remotes = game.ReplicatedStorage:WaitForChild("RemoteEvents")
local buyToolRE = remotes:WaitForChild("BuyTool")
local equippedTools = {}
game.Players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
char.ChildAdded:Connect(function(child)
local equippedTool = char:FindFirstChildOfClass("Tool")
equippedTools[plr] = equippedTool and equippedTool.Name
end)
end)
local plrData = SavingData.LoadData(plr)
local plrCash = plrData and plrData.Cash or startingCurrency.Value
local plrTools = plrData and plrData.Tools or {}
CreateLeaderstats(plr, plrCash)
CreateTools(plr, plrTools)
end)
game.Players.PlayerRemoving:Connect(function(plr)
SavingData.SaveData(plr, equippedTools[plr])
end)
game:BindToClose(function()
for _, plr in pairs(game.Players:GetPlayers()) do
SavingData.SaveData(plr, equippedTools[plr])
end
end)
buyToolRE.OnServerEvent:Connect(function(plr, toolName)
BuyTool(plr, toolName)
end)
local DataStoreService = game:GetService("DataStoreService")
local conf = game.ReplicatedStorage:WaitForChild("Configuration")
local currencyName = conf:WaitForChild("CurrencyName")
local startingCurrency = conf:WaitForChild("StartingCurrency")
local dsKey = conf:WaitForChild("DatastoreKey")
local datastore = DataStoreService:GetDataStore(dsKey.Value)
-- Function to save player data
local function SaveData(player)
if not player then
return
end
local plrKey = player.UserId
local plrCash = player:WaitForChild("leaderstats"):WaitForChild(currencyName.Value).Value
-- Collect player's tools data
local tools = {}
for _, tool in ipairs(player.Backpack:GetChildren()) do
table.insert(tools, tool.Name)
end
local plrData = { Cash = plrCash, Tools = tools }
local success, err = pcall(function()
datastore:SetAsync(plrKey, plrData)
end)
if not success then
warn("Error saving " .. player.Name .. "'s (" .. plrKey .. ") data:\n" .. err)
else
print("Data saved successfully for player:", player.Name)
end
end
-- Connect function to player leaving event
game.Players.PlayerRemoving:Connect(function(player)
SaveData(player)
end)
game:BindToClose(function()
for _, player in ipairs(game.Players:GetPlayers()) do
SaveData(player)
end
end)
-- Function to load player data
local function LoadData(player)
if not player then
return
end
local plrKey = player.UserId
local dataFailedWarning = Instance.new("BoolValue")
dataFailedWarning.Name = "DataLoadFailed"
dataFailedWarning.Value = true
dataFailedWarning.Parent = player
local success, plrData = pcall(function()
return datastore:GetAsync(plrKey)
end)
if success and plrData then
-- Create leaderstats if not already present
local leaderstats = player:FindFirstChild("leaderstats")
if not leaderstats then
leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
end
local currency = leaderstats:FindFirstChild(currencyName.Value)
if not currency then
currency = Instance.new("IntValue")
currency.Name = currencyName.Value
currency.Parent = leaderstats
end
currency.Value = plrData.Cash or startingCurrency.Value
-- Give the player their saved tools
local backpack = player:WaitForChild("Backpack")
for _, toolName in ipairs(plrData.Tools or {}) do
local tool = game.ServerStorage:FindFirstChild(toolName)
if tool then
tool:Clone().Parent = backpack
end
end
dataFailedWarning.Value = false
else
warn("Error loading " .. player.Name .. "'s (" .. plrKey .. ") data.")
end
dataFailedWarning:Destroy()
end
-- Connect function to player joining event
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function()
LoadData(player)
end)
end)
BuyTool (ModuleScript):
local conf = game.ReplicatedStorage:WaitForChild("Configuration")
local currencyName = conf:WaitForChild("CurrencyName")
local canBuyMultipleTimes = conf:WaitForChild("CanBuyItemMultipleTimes")
local keepItemsOnDeath = conf:WaitForChild("KeepItemsOnDeath")
local tools = game.ReplicatedStorage:WaitForChild("Tools")
local coins = game.ReplicatedStorage:WaitForChild("Coins")
local gamepass = game.ReplicatedStorage:WaitForChild("Gamepass")
local remotes = game.ReplicatedStorage:WaitForChild("RemoteEvents")
local buyToolRE = remotes:WaitForChild("BuyTool")
function BuyTool(plr, toolName)
local toolToBuy = nil
-- Check if the tool is in the Tools category
toolToBuy = tools:FindFirstChild(toolName)
-- If not, check if it's in the Coins category
if not toolToBuy then
toolToBuy = coins:FindFirstChild(toolName)
end
-- If still not found, check if it's in the Gamepass category
if not toolToBuy then
toolToBuy = gamepass:FindFirstChild(toolName)
end
-- If the tool wasn't found in any category, return
if not toolToBuy then
warn("Tool '" .. toolName .. "' doesn't exist!")
return
end
local toolConfig = toolToBuy:FindFirstChild("Configuration")
if not toolConfig then
warn("Tool '" .. toolName .. "' doesn't have a Configuration folder!")
return
end
local toolPriceValue = toolConfig:FindFirstChild("Price")
if not toolPriceValue then
warn("Tool '" .. toolName .. "' doesn't have a Price value!")
return
end
local plrCash = plr.leaderstats[currencyName.Value]
local toolPrice = toolPriceValue.Value
if plrCash.Value < toolPrice then
warn("Player " .. plr.Name .. " (" .. plr.UserId .. ") doesn't have enough cash to buy '" .. toolName .. "'!")
return
end
local plrTools = require(game.ReplicatedStorage.ModuleScripts.GetTools)(plr)
-- Check if the player already owns the tool
local alreadyOwnsTool = table.find(plrTools, toolName)
if alreadyOwnsTool then
-- Player already owns the tool, replace it
local existingTool = plr.Backpack:FindFirstChild(toolName)
if existingTool then
existingTool:Destroy()
end
end
-- Deduct the price from the player's cash balance
plrCash.Value -= toolPrice
-- Give the player the new tool
local newTool = toolToBuy:Clone()
newTool.Parent = plr.Backpack
-- If configured to keep items on death, add the new tool to the starter gear
if keepItemsOnDeath.Value then
local starterGear = plr:FindFirstChild("StarterGear")
if starterGear then
newTool:Clone().Parent = starterGear
end
end
-- Notify the client about the purchase
buyToolRE:FireClient(plr, toolToBuy)
end
return BuyTool
CreateTools (ModuleScript):
local tools = game.ReplicatedStorage:WaitForChild("Tools")
local coins = game.ReplicatedStorage:WaitForChild("Coins")
local gamepass = game.ReplicatedStorage:WaitForChild("Gamepass")
local conf = game.ReplicatedStorage:WaitForChild("Configuration")
local keepItemsOnDeath = conf:WaitForChild("KeepItemsOnDeath")
function CreateTools(plr: Player)
local plrTools = require(game.ReplicatedStorage.ModuleScripts.GetTools)(plr)
-- Create tools from the Tools category
for _, toolName in pairs(plrTools) do
local plrTool = tools:FindFirstChild(toolName)
if plrTool then
plrTool:Clone().Parent = plr.Backpack
if keepItemsOnDeath.Value == true then
plrTool:Clone().Parent = plr.StarterGear
end
end
end
-- Create tools from the Coins category
for _, tool in pairs(coins:GetChildren()) do
if plr.Backpack:FindFirstChild(tool.Name) or plr.Character:FindFirstChild(tool.Name) then
tool:Clone().Parent = plr.Backpack
if keepItemsOnDeath.Value == true then
tool:Clone().Parent = plr.StarterGear
end
end
end
-- Create tools from the Gamepass category
for _, tool in pairs(gamepass:GetChildren()) do
if plr.Backpack:FindFirstChild(tool.Name) or plr.Character:FindFirstChild(tool.Name) then
tool:Clone().Parent = plr.Backpack
if keepItemsOnDeath.Value == true then
tool:Clone().Parent = plr.StarterGear
end
end
end
end
return CreateTools
In ServerScriptService is my SavingData ServerScript, aswell as ShopServer, which inside it is a folder called ModuleScripts which contains the BuyTool and CreateTools modulescripts
I used to have 2 module scripts for saving data, but it didn’t work too well for me, so I changed it to a ServerScript, and tried to replicate the way it was referenced there