[help!] datastore script!

Ok guys i’m trying to make a data module for my stats and i used require so i can reference it but its not receiving the module. I can tell the module is doing what it needs to do its just not connected to my stats can anyone plz tell me why this is?

Also before you guys comment I do not want to here recommendations such as datastore2 and stuff like that i wanna do this on my own my own way.

DataModule(Script):


local UserDataService = game:GetService("DataStoreService")
local UserData = UserDataService:GetDataStore("UserData")

local playersData = {}

local AUTOSAVE_WAIT = 60

function EpicsDataStore:ChangeStat(user, statName, value)
	local userID = "Player_"..user.UserId
	assert(typeof(playersData[userID][statName]) == typeof(value))
	 	if assert(typeof(playersData[userID][statName])) == "XP" then
				playersData[userID][statName] = playersData[userID][statName] + value
	else
		
				playersData[userID][statName] = value
		end
	end
	
	
	local function setupUserData(user)
		local userID = "Player_"..user.UserId
		local success, data = pcall(function()
			return UserData:GetAsync(userID)
		end)
		if success then
			if data then
				playersData[userID] = data
			else
				playersData[userID] = {Experience = 0}
			end
		else
			warn("Cannot Access Data Store For User!")
		end
	end
	
	local function saveUserData(userID)
		if playersData[userID] then
			local tries = 0
			local success
			repeat
				tries = tries + 1
				success = pcall(function()
					UserData:SetAsync(userID, playersData[userID])
				end)
				if not success then
					warn("Cannot Save Data For User: "..userID)
				end
			until tries == 3 or success
		end
	end
	
	local function saveOnExit(user)
		local userID = "Player_".. user.UserId
		saveUserData(userID)
	end
	
	local function autosave()
		while wait(AUTOSAVE_WAIT) do
			for userID, data in pairs(playersData) do
				saveUserData(userID)
			end
		end
	end
	
	spawn(autosave)
	
	game.Players.PlayerAdded:Connect(setupUserData)
	
	game.Players.PlayerRemoving:Connect(saveOnExit)

return EpicsDataStore

stats(script):
local EpicsDataModule = require(script.DataModule)
local UserDataService = game:GetService("DataStoreService")
local UserData = UserDataService:GetDataStore("UserData")

playersData = {}

local Stats = Instance.new("Folder")
Stats.Name = "leaderstats"
local Experience = Instance.new("IntValue")
Experience.Parent = Stats
Experience.Name = "XP"
Experience.Value = Experience.Value

game.Players.PlayerAdded:Connect(function(user)
	local userID = user.UserId
	Stats.Parent = user
	user.leaderstats.XP.Value = UserData:GetAsync(userID, playersData)
end)
4 Likes

Caught your error. A pcall is used to stop the output from sending an error message.

In this block, “data” would refer to the error message that would follow if there is one. With a pcall, only the error, or the returned data is a possibility, if that makes sense.

The 2 scenarios are success, (the data would be returned and referenced as “success”)
or error (in this function the error message would be returned and referenced as “data”).

It’s a paradox because if it’s successful, it checks for the error message, and if it’s not well, it doesn’t do anything. In addition, you don’t need to use the return function of a pcall, because it will already automatically return info. Knowing this you can change your function to…

local success, Error = pcall(function()
UserData:GetAsync(userID)
end)

if success ~= nil then
playersData[userID] = data
elseif Error then
--etc 

end

I recommend visiting the article on Lua globals (which include pcalls). It’s very helpful

3 Likes

No, a pcall is used to catch an error and prevent the error from terminating the thread. pcalls are handy for error handling (what your code should do if an error is thrown from a function call).

Yes you do. The returns of pcall are a boolean and variable arguments. The boolean determines if the function was successful in running and didn’t throw an error, hence popular use of success as the variable name for the first return.

If success is true, anything returned in pcall will be returned as well. If success is false, only one argment which is a string representing the error will be returned. This is why the following conventions work for pcalls:

local success, a, b = pcall(function ()
    return "A", "B"
end)

local returns = {pcall(function ()
    return "A", "B"
end)}

local success, data = pcall(DataStore.GetAsync, DataStore, key)

Success can’t ever be nil. It’s a boolean that’s guaranteed to be true or false and the first return value of a pcall. pcall is a callback.

3 Likes

How would I link the data module to the stats cuz I see the module working it’s just not connected to the stats for some reason

1 Like

I’m confused as to what your problem is. You vaguely described the issue and left your entire script (or maybe even two, I can’t tell with the lack of formatting) on the thread. Mind explaining what the situation is clearly and pinpointing a source of error? Maybe even a console error?

There is no error what I am trying to say is I’m trying to reference the module in my script so it can help save a Players experience but I don’t know how to make it so it does so.

For example let’s say I’m trying to save a Players level in with my data module how would I add or connect the players stats to the module in my stats script so I can save it.

I’m using require(script.DataModule) but it doesn’t seem to be saving the stats

it’s really hard to explain sorry if I confuse you

Not the complete solution but here:

local Stats = Instance.new("Folder")
Stats.Name = "leaderstats"
local Experience = Instance.new("IntValue")
Experience.Parent = Stats
Experience.Name = "XP"
Experience.Value = Experience.Value

game.Players.PlayerAdded:Connect(function(user)
	local userID = user.UserId
	Stats.Parent = user
	user.leaderstats.XP.Value = UserData:GetAsync(userID, playersData)
end)

When the second player joins, the first player’s stats will get shifted to the second player.
Maybe try creating the new stats inside the player added function.

I used ~= in case the datastore was empty. But other than that, thanks for letting me know!

But I get the users data from the UserId so how would this shift to another player it would have to Verify if the Players ID is a match correct?