Am I an idiot, or what's wrong here?

So, I recently started to create a new game. Got around to the DataStores a little while ago, yet they don’t work on saving (loading works. Tested it with the DataStore editor)

The saving of the player’s data does not work at all, and I have been very confused.
I use a Module Script for the saving/loading to keep things neat & organized; however, I’m unsure if this is the problem. I highly doubt it because in all of my other games I use a module script for saving & loading as well, yet it works just fine in those games.
And yes, Studio Access to API Services IS on.

I also had an issue with my BindToClose, but I resolved that in under a minute.
I commonly make really stupid mistakes while coding, even with six years of experience up my sleeve. I just want to see if anyone else can spot something I’m missing.


Here is my module script code (both saving and loading):

local Players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverStorage = game:GetService("ServerStorage")
local dataStoreService = game:GetService("DataStoreService")
local physicsService = game:GetService("PhysicsService")

local dataStore = dataStoreService:GetDataStore("DataStore")

local mainGame = replicatedStorage:WaitForChild("MainGame")
local remotes = mainGame:WaitForChild("Remotes")
local gameValues = mainGame:WaitForChild("GameValues")

local module = {}

function module.LoadData(player)
	--// Stats
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	
	local cash = Instance.new("IntValue")
	cash.Name = "Cash"
	cash.Value = 0
	cash.Parent = leaderstats
	
	local wins = Instance.new("IntValue")
	wins.Name = "Wins"
	wins.Value = 0
	wins.Parent = leaderstats
	
	local deaths = Instance.new("IntValue")
	deaths.Name = "Deaths"
	deaths.Value = 0
	deaths.Parent = leaderstats
	
	--// Level
	local level = Instance.new("IntValue")
	level.Name = "Level"
	level.Value = 0
	level.Parent = leaderstats
	
	local currentExp = Instance.new("IntValue")
	currentExp.Name = "CurrentExp"
	currentExp.Value = 0
	currentExp.Parent = level

	local maxExp = Instance.new("IntValue")
	maxExp.Name = "MaxExp"
	maxExp.Value = 150
	maxExp.Parent = level
	
	--// Other
	local equippedPack = Instance.new("StringValue")
	equippedPack.Name = "EquippedPack"
	equippedPack.Value = "Default"
	equippedPack.Parent = player
	
	local inMenu = Instance.new("BoolValue")
	inMenu.Name = "InMenu"
	inMenu.Value = true
	inMenu.Parent = player
	
	--// Load Data
	local cashData, winsData, deathsData
	local levelData, currentExpData, maxExpData
	local equippedPackData
	
	local success, errorMessage = pcall(function()
		cashData = dataStore:GetAsync("cash-"..player.UserId)
		winsData = dataStore:GetAsync("wins-"..player.UserId)
		deathsData = dataStore:GetAsync("deaths-"..player.UserId)
		
		levelData = dataStore:GetAsync("level-"..player.UserId)
		currentExpData = dataStore:GetAsync("currentExp-"..player.UserId)
		maxExpData = dataStore:GetAsync("maxExp-"..player.UserId)
		
		equippedPackData = dataStore:GetAsync("equippedPack-"..player.UserId)
	end)
	
	if success then
		cash.Value = cashData or cash.Value
		wins.Value = winsData or wins.Value
		deaths.Value = deathsData or deaths.Value
		
		level.Value = levelData or level.Value
		currentExp.Value = currentExpData or currentExp.Value
		maxExp.Value = maxExpData or maxExp.Value
		
		equippedPack.Value = equippedPackData or equippedPack.Value
		
		print("Loaded data for "..player.Name)
	else
		cash.Value = 0
		wins.Value = 0
		deaths.Value = 0

		level.Value = 0
		currentExp.Value = 0
		maxExp.Value = 150

		equippedPack.Value = "Default"
		
		warn("No data for "..player.Name.."!")
	end
	
	--// Player Collision
	local character = player.Character or player.CharacterAdded:Wait()
	
	for _, part in pairs(character:GetChildren()) do
		if part:IsA("BasePart") then
			part.CollisionGroup = "Players"
		end
	end
end

function module.SaveData(player)
	local success, errorMessage = pcall(function()
		dataStore:SetAsync("cash-"..player.UserId, player.Cash.Value)
		dataStore:SetAsync("wins-"..player.UserId, player.Wins.Value)
		dataStore:SetAsync("deaths-"..player.UserId, player.Deaths.Value)

		dataStore:SetAsync("level-"..player.UserId, player.Level.Value)
		dataStore:SetAsync("currentExp-"..player.UserId, player.Level.CurrentExp.Value)
		dataStore:SetAsync("maxExp-"..player.UserId, player.Level.MaxExp.Value)
		
		dataStore:SetAsync("equippedPack-"..player.UserId, player.EquippedPack.Value)
		
		print("Saved data for "..player.Name)
	end)
end

return module

And also the only Server Script code involved with it:

Players.PlayerAdded:Connect(function(player)
	playersLeft += 1
	leaderstats.LoadData(player)
end)

Players.PlayerRemoving:Connect(function(player)
	playersLeft -= 1
	leaderstats.SaveData(player)
end)

----
----
----
----
----
--// Ignore the empty comments above lol. I added those to imitate the rest of the code before BindToClose

game:BindToClose(function()
	task.wait(30)
end)

Any help is really appreciated, even if you cannot find me a solution. Thank you!


Best regards,
Amora

Oh yeah, and here’s an example from one of my other games. All of the code in this game works just fine! It’s so confusing why it refuses to work in my new game, but I’m probably just being a doofus


Anyways:

Module

local Players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverStorage = game:GetService("ServerStorage")
local lighting = game:GetService("Lighting")
local tweenService = game:GetService("TweenService")
local dataStoreService = game:GetService("DataStoreService")
local marketPlaceService = game:GetService("MarketplaceService")
local badgeService = game:GetService("BadgeService")

local dataStore = dataStoreService:GetDataStore("DataStore")

local mainGame = replicatedStorage:WaitForChild("MainGame")
local remotes = mainGame:WaitForChild("Remotes")

local vipGamePass = 42960558
local extraSpeedGamePass = 43113220

local metDeveloperBadge = 2127847888
local playBadge = 2127861595

local gameDevTag = {}
local adminTag = {56437368, 411648684, 3231488167, 1637468247, 681235830, 117648590, 1226217219}
local soundDesignerTag = {}

local diamondTag = {3231488167}
local crucible = {56437368}

local plrStats = {}

function plrStats.LoadChatTags(player)
	local tags = Instance.new("Folder",player)
	tags.Name = "Tags"
	
	if player.UserId == 56437368 then
		local newTag = Instance.new("IntValue",tags)
		newTag.Name = "🛠"
		
		local chatColor = Instance.new("Color3Value",newTag)
		chatColor.Name = "ChatColor"
		chatColor.Value = Color3.fromRGB(85, 255, 0)
		
		local tagColor = Instance.new("Color3Value",newTag)
		tagColor.Name = "TagColor"
		tagColor.Value = Color3.fromRGB(253, 41, 67)
	elseif table.find(diamondTag, player.UserId) then
		local newTag = Instance.new("IntValue",tags)
		newTag.Name = "💎"

		local chatColor = Instance.new("Color3Value",newTag)
		chatColor.Name = "ChatColor"
		chatColor.Value = BrickColor.new("Pink").Color

		local tagColor = Instance.new("Color3Value",newTag)
		tagColor.Name = "TagColor"
		tagColor.Value = Color3.fromRGB(255, 102, 204)
	elseif table.find(gameDevTag, player.UserId) then
		local newTag = Instance.new("IntValue",tags)
		newTag.Name = "⚙️"

		local chatColor = Instance.new("Color3Value",newTag)
		chatColor.Name = "ChatColor"
		chatColor.Value = BrickColor.new("Electric blue").Color

		local tagColor = Instance.new("Color3Value",newTag)
		tagColor.Name = "TagColor"
		tagColor.Value = Color3.fromRGB(9, 137, 207)
	elseif table.find(adminTag, player.UserId) then
		local newTag = Instance.new("IntValue",tags)
		newTag.Name = "🛡️"

		local chatColor = Instance.new("Color3Value",newTag)
		chatColor.Name = "ChatColor"
		chatColor.Value = BrickColor.new("Really red").Color

		local tagColor = Instance.new("Color3Value",newTag)
		tagColor.Name = "TagColor"
		tagColor.Value = Color3.fromRGB(255, 0, 0)
	elseif table.find(soundDesignerTag, player.UserId) then
		local newTag = Instance.new("IntValue",tags)
		newTag.Name = "💿"

		local chatColor = Instance.new("Color3Value",newTag)
		chatColor.Name = "ChatColor"
		chatColor.Value = BrickColor.new("Bright violet").Color

		local tagColor = Instance.new("Color3Value",newTag)
		tagColor.Name = "TagColor"
		tagColor.Value = Color3.fromRGB(107, 50, 124)
	elseif marketPlaceService:UserOwnsGamePassAsync(player.UserId, vipGamePass) then
		local newTag = Instance.new("IntValue",tags)
		newTag.Name = "👑"

		local chatColor = Instance.new("Color3Value",newTag)
		chatColor.Name = "ChatColor"
		chatColor.Value = BrickColor.new("Deep orange").Color

		local tagColor = Instance.new("Color3Value",newTag)
		tagColor.Name = "TagColor"
		tagColor.Value = Color3.fromRGB(255, 176, 0)
	end
	
end

function plrStats.LoadData(player)
	local playerData = replicatedStorage.MainGame.GameStorage.Templates.PlayerDataFolder:Clone()
	playerData.Name = player.Name
	playerData.Parent = replicatedStorage.MainGame.GameStorage.PlayerData
	
	local serverPlayerData = serverStorage.MainGame.Templates.PlayerDataFolder:Clone()
	serverPlayerData.Name = player.Name
	serverPlayerData.Parent = serverStorage.MainGame.PlayerData
	
	local inMenu = Instance.new("BoolValue")
	inMenu.Name = "InMenu"
	inMenu.Value = false
	inMenu.Parent = player
	
	local isBanned = Instance.new("BoolValue")
	isBanned.Name = "IsBanned"
	isBanned.Value = false
	isBanned.Parent = player
	
	local banReason = Instance.new("StringValue")
	banReason.Name = "Reason"
	banReason.Value = ""
	banReason.Parent = isBanned
	
	local timesKicked = Instance.new("IntValue")
	timesKicked.Name = "TimesKicked"
	timesKicked.Value = 0
	timesKicked.Parent = player
	
	local inventory = Instance.new("Folder")
	inventory.Name = "Inventory"
	inventory.Parent = serverPlayerData
	
	local equipped = Instance.new("StringValue")
	equipped.Name = "Equipped"
	equipped.Parent = serverPlayerData
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name =  "leaderstats"
	leaderstats.Parent = player
	
	local level = Instance.new("IntValue")
	level.Name =  "Level"
	level.Value = 0
	level.Parent = leaderstats

	local exp = Instance.new("IntValue")
	exp.Name = "CurrentExp"
	exp.Value = 0
	exp.Parent = level

	local maxExp = Instance.new("IntValue")
	maxExp.Name = "MaxExp"
	maxExp.Value = 150
	maxExp.Parent = level
	
	local cash = Instance.new("IntValue")
	cash.Name = "Cash"
	cash.Value = 0
	cash.Parent = leaderstats
	
	local gems = Instance.new("IntValue")
	gems.Name = "Gems"
	gems.Value = 0
	gems.Parent = player
	
	local wins = Instance.new("IntValue")
	wins.Name = "Wins"
	wins.Value = 0
	wins.Parent = leaderstats
	
	local rewardsClaimed = Instance.new("Folder")
	rewardsClaimed.Name = "RewardsClaimed"
	rewardsClaimed.Parent = player
	
	local cashData, levelData, currentExpData, maxExpData, gemsData, winsData
	local bannedData, reasonData
	local weaponsData
	local equippedData
	local rewardsData
	
	local success,errorMessage = pcall(function()
		cashData = dataStore:GetAsync("cash-"..player.UserId)
		gemsData = dataStore:GetAsync("gems-"..player.UserId)
		
		levelData = dataStore:GetAsync("level-"..player.UserId)
		currentExpData = dataStore:GetAsync("currentExp-"..player.UserId)
		maxExpData = dataStore:GetAsync("maxExp-"..player.UserId)
		
		winsData = dataStore:GetAsync("wins-"..player.UserId)
		
		weaponsData = dataStore:GetAsync("weapons-"..player.UserId)
		equippedData = dataStore:GetAsync("equipped-"..player.UserId)
		
		rewardsData = dataStore:GetAsync("rewards-"..player.UserId)
		
		bannedData = dataStore:GetAsync("banned-"..player.UserId)
		reasonData = dataStore:GetAsync("banReason-"..player.UserId)
	end)
	
	if success then
		cash.Value = cashData or cash.Value
		gems.Value = gemsData or gems.Value
		wins.Value = winsData or wins.Value
		
		level.Value = levelData or level.Value
		exp.Value = currentExpData or exp.Value
		maxExp.Value = maxExpData or maxExp.Value
		
		isBanned.Value = bannedData or isBanned.Value
		banReason.Value = reasonData or banReason.Value
		
		if weaponsData then
			for _, weapon in pairs(weaponsData) do
				if serverStorage:WaitForChild("MainGame"):WaitForChild("Tools"):WaitForChild("ShopTools"):FindFirstChild(weapon) then
					local weaponClone = serverStorage:WaitForChild("MainGame"):WaitForChild("Tools"):WaitForChild("ShopTools"):FindFirstChild(weapon):Clone()
					weaponClone.Parent = inventory
				end
				
			end
		else
			warn("No weapons data for "..player.Name)
		end
		
		if equippedData then
			equipped.Value = equippedData or equipped.Value
			player:WaitForChild("PlayerGui")
			remotes:WaitForChild("SendEquipped"):FireClient(player, equippedData)
		end
		
		if rewardsData then
			for _, reward in pairs(rewardsData) do
				local rewardTag = Instance.new("StringValue")
				rewardTag.Name = reward
				rewardTag.Parent = rewardsClaimed
			end
		else
			warn(player.Name.." has not collected any rewards!")
		end
		
	else
		warn("No Data for "..player.Name.."!")
	end
	
	if marketPlaceService:UserOwnsGamePassAsync(player.UserId, vipGamePass) then
		local character = player.Character or player.CharacterAdded:Wait()
		
		player.Character:WaitForChild("Humanoid").MaxHealth = (100 * 0.2 + 100)
		player.Character:WaitForChild("Humanoid").Health = (100 * 0.2 + 100)
	end
	
	if isBanned.Value == true and player.UserId ~= 56437368 then
		player:Kick(banReason.Value)
	end
	
	coroutine.wrap(function()
		while player do
			task.wait(300)
			if marketPlaceService:UserOwnsGamePassAsync(player.UserId, vipGamePass) then
				player.leaderstats.Cash.Value += 1500
			end
		end
	end)()
	
	if Players:FindFirstChild("RoboBoy013") then
		local Plrs = game.Players:GetPlayers()
		
		for i = 1, #Plrs do
			local plr = Plrs[i]
			
			if not badgeService:UserHasBadgeAsync(plr.UserId, metDeveloperBadge) then
				badgeService:AwardBadge(plr.UserId, metDeveloperBadge)
				
				local success, result = pcall(function()
					return badgeService:GetBadgeInfoAsync(metDeveloperBadge)
				end)

				remotes:WaitForChild("PlayerGotBadge"):FireAllClients(player, result.Name)
			end
		end
	end
	
	if not badgeService:UserHasBadgeAsync(player.UserId, playBadge) then
		local success, result = pcall(function()
			return badgeService:GetBadgeInfoAsync(playBadge)
		end)
		
		remotes:WaitForChild("PlayerGotBadge"):FireAllClients(player, result.Name)
		
		badgeService:AwardBadge(player.UserId, playBadge)
	end
end

function plrStats.SaveData(player)
	local success, errorMessage = pcall(function()
		dataStore:SetAsync("cash-"..player.UserId, player.leaderstats.Cash.Value)
		dataStore:SetAsync("gems-"..player.UserId, player.Gems.Value)
			
		dataStore:SetAsync("level-"..player.UserId, player.leaderstats.Level.Value)
		dataStore:SetAsync("currentExp-"..player.UserId, player.leaderstats.Level.CurrentExp.Value)
		dataStore:SetAsync("maxExp-"..player.UserId, player.leaderstats.Level.MaxExp.Value)
		
		dataStore:SetAsync("wins-"..player.UserId, player.leaderstats.Wins.Value)
		
		dataStore:SetAsync("banned-"..player.UserId, player.IsBanned.Value)
		dataStore:SetAsync("banReason-"..player.UserId, player.IsBanned.Reason.Value)
			
		local weapons = serverStorage:WaitForChild("MainGame"):WaitForChild("PlayerData"):FindFirstChild(player.Name).Inventory:GetChildren()
		local weaponsTable = {}
			
		for _, v in pairs(weapons) do
			table.insert(weaponsTable, v.Name)
		end
			
		dataStore:SetAsync("weapons-"..player.UserId, weaponsTable)
			
		if serverStorage:WaitForChild("MainGame"):WaitForChild("PlayerData"):FindFirstChild(player.Name).Equipped.Value ~= nil then
			local equippedVal = serverStorage:WaitForChild("MainGame"):WaitForChild("PlayerData"):FindFirstChild(player.Name).Equipped
				
			dataStore:SetAsync("equipped-"..player.UserId, equippedVal.Value)
		end
		
		local plrRewards = player:WaitForChild("RewardsClaimed"):GetChildren()
		local rewardsTable = {}
		
		for _, w in pairs(plrRewards) do
			table.insert(rewardsTable, w.Name)
		end
		
		dataStore:SetAsync("rewards-"..player.UserId, rewardsTable)
		
		print("Saved "..player.Name.."'s Data.")
	end)
end

function plrStats.AntiBan(player, reason)
	player.IsBanned.Value = true
	player.IsBanned.Reason.Value = "You have been banned by the Anti-Cheat. Reason: "..reason..". This ban is permanent"
	
	player:Kick(player.IsBanned.Reason.Value)
end

return plrStats

Server:

Players.PlayerAdded:Connect(function(player)
	playersLeft += 1
	leaderstats.LoadData(player)
end)

Players.PlayerRemoving:Connect(function(player)
	playersLeft -= 1
	leaderstats.SaveData(player)
end)

----
----

game:BindToClose(function()
	while playersLeft > 0 do
		bindableEvent.Event:Wait()
	end
end)

Practically the same code. It’s so strange.

Does “Saved data for” even print? If not, have you tried printing the errorMessage? It should show what could have happened.

It does print, yes. More of the reason as to why I am confused.

I haven’t tried printing the error message, but with “Saved data for” actually printing, I assume there isn’t one. I’ll change some stuff real quick to print the error message.

DAMN I’M AN IDIOT :rofl: :sob:

The error message does print and returned “Cash is not a valid member of player” because I forgot to do player.leaderstats.Cash
I typed in player.Cash instead :woman_facepalming:

Like I said, I’m prone to making stupid mistakes. Wasted so much time trying stuff

1 Like

I will recommend you to put all the different data on a table and save that table because if you do that amount of setasync request your game will have a lot of data loss

1 Like

That’s a good idea. I do that normally, but late into development. Even one of my biggest games still uses a million SetAsyncs because I’ve been too lazy to change it to save into a table instead.

It’s probably better to do so now so I don’t get lazy in the future like with all of my other games :laughing:

Yeahh also i recommend you to use UpdateAsync instead of SetAsync

1 Like

Always forget about UpdateAsync’s existence lol. I know in the back of my mind that it exists and is way better, but the actual conscious scripting part of me just uses SetAsync since that’s what I’ve used pretty much since I started coding.
I’ve gotta get into the habit of using UpdateAsync

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.