Need help with Datastores again

My Datastore works in game but there’s an issue where it only saves one person’s data rather than the rest, It only saves one person’s stats at a time only if they are in a server by themselves. If there’s anything wrong with it that doesn’t allow other players to save data, please let me know. Thanks.

The script is:

local datastoreservice = game:GetService("DataStoreService")
local datastore = datastoreservice:GetDataStore("testing23")
local Holder = script.Stats
    
--//PlayerAdded
game.Players.PlayerAdded:Connect(function(players)
    
    local Key = "PlayerID" .. players.userId
    local GetSave = datastore:GetAsync(Key)
    
    local DataFolder = Instance.new("Folder", players)
    DataFolder.Name = "Stats"
    
    local gold = Instance.new('IntValue') -- Gold
    gold.Name = 'Gold'
    gold.Parent = Holder
    
    local statPoints = Instance.new('IntValue') 
    statPoints.Name = 'StatPoints'
    statPoints.Parent = Holder
    
    --//Level
    
    local level = Instance.new('IntValue') -- Level
    level.Name = 'Level'
    level.Parent = Holder
    
    local exp = Instance.new('IntValue') -- Exp
    exp.Name = 'Exp'
    exp.Parent = Holder
    
    local nexp = Instance.new('IntValue') -- Nexp
    nexp.Name = 'Nexp'
    nexp.Parent = Holder
    
    --//Stats

    local vitality = Instance.new('IntValue') -- Vitality
    vitality.Name = 'Vitality'
    vitality.Parent = Holder
    
    local defense = Instance.new('IntValue') -- Defense
    defense.Name = 'Defense'
    defense.Parent = Holder
    
    local stamina = Instance.new('IntValue') -- Stamina
    stamina.Name = 'Stamina'
    stamina.Parent = Holder
    
    local mana = Instance.new('IntValue') -- Mana
    mana.Name = 'Mana'
    mana.Parent = Holder
    
    local power = Instance.new('IntValue') -- Power
    power.Name = 'Power'
    power.Parent = Holder
    
    for i, Stats in pairs (Holder:GetChildren()) do
        local Newstats = Instance.new(Stats.ClassName)    
        Newstats.Name = Stats.Name
        Newstats.Value = Stats.Value
        Newstats.Parent = DataFolder
    end
if GetSave then
        for i, Stats in pairs(DataFolder:GetChildren()) do
            DataFolder[Stats.Name].Value = GetSave[i]
        end
        
    else
        
        local SaveStats = {}
        
        for i, Stats in pairs(DataFolder:GetChildren()) do 
            table.insert(SaveStats, Stats.Value)
        end
        datastore:SetAsync(Key, SaveStats)
        
    end
    
    while wait(10) do
        
        local SaveStats = {}
        
        for i, Stats in pairs(DataFolder:GetChildren()) do 
            table.insert(SaveStats, Stats.Value)
        end
        datastore:SetAsync(Key, SaveStats)
        
        print('DataSaved')
    end
    
game.Players.PlayerRemoving:Connect(function(ReturningPlayer)
    
    local Key = "PlayerID" .. ReturningPlayer.userId
    
    local SaveStats = {}
        
        for i, Stats in pairs(DataFolder:GetChildren()) do 
            table.insert(SaveStats, Stats.Value)
        end
        datastore:SetAsync(Key, SaveStats)
        
        print('DataSaved')
    
end)
end)
2 Likes

smh I don’t recommend using a datastore system like this.

here is a simple script you can edit.

local datastoreservice = game:GetService("DataStoreService") --// A service
local gamedata = datastoreservice:GetDataStore("GameData") --// Actual Data Module
local newdata = {}

function checkplayerinformation(player)
	local data = gamedata:GetAsync(player.UserId) --// Getting Player's Data 
	if data then
		print("Player Has Data!")
        newdata[player.UserId] = data
	else
		data = {
			--// Data you want for the player
			level = 0,
			randomvalue = 0,
		}
		newdata[player.UserId] = data
		print("Gave the player data!")
	end
	return data
end

function getplayerdata(player)
	local data = newdata[player.UserId]
	if data then
		return data
	else
		print("error happened when getting data!")
	end
	return false
end

function editplayerdata(player, editing, value)
	local data = newdata[player.UserId]
	if data then
		data[editing] = value
	else
		print("error when editing data")
	end
end

function setplayerdata(player, data)
	if not data then
		return false
	end
	gamedata:SetAsync(player.UserId, data)
	return true
end

--// you can make it do like editplayerdata(player, "level", 100)
--// you'll need to do some editing so you can make it so the level will also change with the board or a custom board

game.Players.PlayerAdded:Connect(function(player)
	if checkplayerinformation(player) then
		local good, bad = pcall(function()
			local data = getplayerdata(player)
			if data then
			--// code to happen with data
			--// example: player.leaderstats.level = data.level
			end
		end)
		if not good then
			warn("!! Data Load Error", bad)
		end
	else
		print("An error has happened!")	
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local settingdata = getplayerdata(player)
	if settingdata then
		setplayerdata(player, settingdata)
		newdata[player.UserId] = nil
	else
		print("error when saving data!")
	end
end)


--// Script is untested
1 Like

Thanks! But i’m not really sure how to use modules, is there any tutorial or anything that I could use that would work for this?

Oof, I just fixed up your script and made it a bit more simple to read.

local datastoreservice = game:GetService("DataStoreService")
local datastore = datastoreservice:GetDataStore("testing23")
local Holder = script.Stats
    
local function CreateNew(Obj, Name, Parent)
	local New = Instance.new(Obj)
	New.Name = Name
	New.Parent = Parent
	return New
end

local function ReturnObj(Player, Name)
	for i,v in next, Player:GetChildren() do
		if v.Name == Name then
			return v
		end
	end
	return nil
end
--//PlayerAdded
game:GetService('Players').PlayerAdded:Connect(function(Player)
    
    local Key = "PlayerID" .. Player.userId

    local GetSave = datastore:GetAsync(Key)
    
    local DataFolder = CreateNew("Folder",'Stats',Player)
    
    local gold = CreateNew("IntValue",'Gold',Holder)
    
    local statPoints = CreateNew("IntValue",'StatPoints',Holder)
    
    local level = CreateNew("IntValue",'Level',Holder) -- Level
    
    local exp = CreateNew("IntValue",'Exp',Holder) -- Exp
    
    local nexp = CreateNew("IntValue",'Nexp',Holder) -- Nexp
    
    --//Stats

    local vitality = CreateNew("IntValue",'Vitality',Holder) -- Vitality
    
    local defense = CreateNew("IntValue",'Defense',Holder) -- Defense
    
    local stamina = CreateNew("IntValue",'Stamina',Holder) -- Stamina
    
    local mana = CreateNew("IntValue",'Mana',Holder) -- Mana
    
    local power = CreateNew("IntValue",'Power',Holder) -- Power
    
    for i, Stats in pairs (Holder:GetChildren()) do
        local Newstats = CreateNew(Stats.ClassName, Stats.Name, DataFolder)
        Newstats.Value = Stats.Value
    end

	if GetSave then --data is avaliable
        for i, Stats in pairs(DataFolder:GetChildren()) do
            DataFolder[Stats.Name].Value = GetSave[i]
        end
    else --data is not avaliable
        local SaveStats = {}
        for i, Stats in pairs(DataFolder:GetChildren()) do 
            table.insert(SaveStats, Stats.Value)
        end
        datastore:SetAsync(Key, SaveStats)
    end
    
    while wait(10) do
        local SaveStats = {}
        for i, Stats in pairs(DataFolder:GetChildren()) do 
            table.insert(SaveStats, Stats.Value)
        end
        datastore:SetAsync(Key, SaveStats)
        print('DataSaved')
    end
end)

--You did not end the PlayerAdded function, which caused the error
game:GetService('Players').PlayerRemoving:Connect(function(Player)
    local Key = "PlayerID" .. Player.userId
    local SaveStats = {}
	local DataFolder = ReturnObj(Player, "Stats")
	if DataFolder then
		for i, Stats in pairs(DataFolder:GetChildren()) do 
	        table.insert(SaveStats, Stats.Value)
	    end
	    datastore:SetAsync(Key, SaveStats)
	 	print('DataSaved')
	else
		print("Could not cache folder")
	end
end)

If you wish to use the other person’s script that’s fine.

1 Like

It isn’t a module btw, though modules are better, I just went with how you used it as a script.

1 Like


I just tested my thing, it is now tested, and if you use it properly it should work

1 Like

Just so you know, I just updated a little bug

Also a small nitpick, never directly reference a service in your script like you did. Always reference it using the :GetService() function. If you rename a service, that can and will break your script. While I am sure you weren’t intending to, it is still always good practice. That is also a friendly reminder for any local scripts you might have, as if those do the same thing, and exploiter could rename them rendering the script useless. In certain situations, that can be very bad. Just thought I would point it out! :wink:

1 Like

How would you make tools save with the DataStore? Gold, EXP, and levels all save perfectly but tools are a bit confusing.

Your system needs reworked. You also aren’t doing pcall checks for errors which will make losing data very easy if it doesn’t save AND load the first time.

I recommend taking a look at my simple method of Datastores

1 Like

you would create a table in the

data = {
level = 0,
somethingrandom = 0,
}

you would make it like this

data = {
tools = {},
level = 0,
somethingrandom = 0,
}

tools would be your indicator of what tools the player should have, you would have to create it yourself but it should be easy

example:

--// table something like this
table.insert(getplayerdata(player).tools, game.Workspace.Tool)
--// getting the tools
local tool = getplayerdata(player).tools[1] --// the [1] would be the index of number of tools
tool:Clone().Parent = player.Backpack --// places in backpack
2 Likes

You can’t save a Tool as-is into a datastore, as it is an Instance it doesn’t get serialized into JSON

What I recommend instead would be to store the Tool.Name, and then when the Player joins the game again, find the tool by its name wherever you store all your tools, then clone it from there

It was an example.

Here’s what you can do if you’re trying to save Gold, xp, etc.

This is what I use for my new Roman Genre and what I have previously done when working with AJCs.


local ReplicatedStorage = game:GetService("ReplicatedStorage")

local MarketplaceService = game:GetService("MarketplaceService")

local HttpService = game:GetService("HttpService")

local Events = ReplicatedStorage:WaitForChild("Events")

local GetData = Events:WaitForChild("GetData")

local GetDataRemote = Events:WaitForChild("GetDataRemote")

local SaveDataServer = Events:WaitForChild("SaveDataServer")

local DataStore = game:GetService("DataStoreService"):GetDataStore("PlayerData", "3/2")

local Players = {}

---------------------------------------------------------

-- Default Data

function getDefaultData()

return {

Inventory = {"Axe","Pickaxe","Torch"},

ItemsEquipped = {"Tanned Tunic"},

Primary = {},

Secondary = {},

Head = {},

Torso = {"Tanned Tunic"},

Backpack = {},

Horses = {},

Quests = {},

Generation = "",

Family = "",

Tutorial = false,

Level = 1,

Experience = 0,

Jailed = 0,

Hunger = 100,

Money = 25,

Wood = 0,

Iron = 0,

Silver = 0,

Gold = 0,

Copper = 0,

Leather = 0,

Cloth = 0

}

end
1 Like