Help Datastore to load stuff as Tables(or in a way i want it to be)

Hi! I need help about the datastore i am using to load things as expected to be…
I mean I’ll add stuff as StringValue from Server when Quest is done etc. but From what i have found…
It saves as i want it to be but Doesn’t load…

Example:
I add item or something else to Inventory
it saves
but doesn’t load
only loads already existing stats.

Here is the script:

local players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverScriptService = game:GetService("ServerScriptService")
local serverSettings = replicatedStorage.Stats:WaitForChild("AboutServer")
local module = {}

function module.Save(player)
	if players:FindFirstChild(player.Name) and player:FindFirstChild("IsLoaded") then
		local status, message = pcall(function()
			local Achievements = {}
			for _,achievements in pairs(player.Achievements:GetChildren()) do
				if achievements:IsA("ValueBase") then
					table.insert(Achievements, {achievements.Name, achievements.Value})
				end
			end
			local Equipped = {}
			for _,equipped in pairs(player.Equipped:GetChildren()) do
				if equipped:IsA("ValueBase") then
					table.insert(Equipped, {equipped.Name, equipped.Value})
				end
			end
			local Inventory = {}
			for _,inventorie in pairs(player.Inventory:GetChildren()) do
				if inventorie:IsA("ValueBase") then
					table.insert(Inventory, {inventorie.Name, inventorie.Value})
				end
			end
			local Stats = {}
			for _,stats in pairs(player.Stats:GetChildren()) do
				if stats:IsA("ValueBase") then
					table.insert(Stats, {stats.Name, stats.Value})
				end
			end
			local BasicStuff = {}
			for _,basicstuff in pairs(player.BasicStuff:GetChildren()) do
				if basicstuff:IsA("ValueBase") then
					table.insert(BasicStuff, {basicstuff.Name, basicstuff.Value})
				end
			end
			local Titles = {}
			for _,titles in pairs(player.Titles:GetChildren()) do
				if titles:IsA("ValueBase") then
					table.insert(Titles, {titles.Name, titles.Value})
				end
			end
			local Quests = {}
			for _,quests in pairs(player.Quests:GetChildren()) do
				if quests:IsA("ValueBase") then
					table.insert(Quests, {quests.Name, quests.Value})
				end
			end
			local CompletedQuests = {}
			for _,completedquests in pairs(player.CompletedQuests:GetChildren()) do
				if completedquests:IsA("ValueBase") then
					table.insert(CompletedQuests, {completedquests.Name, completedquests.Value})
				end
			end
			local saveFile = {Achievements, Equipped, Inventory, Stats, BasicStuff, Titles, Quests, CompletedQuests}
			game:GetService("DataStoreService"):GetDataStore("ZenithOfZeroth"):SetAsync(player.UserId, saveFile)
		end)
		if status ~= true then
			print(player.Name .. " couldn't save, retrying... \n" .. message)
			wait(10)
			module.Save(player)
		else
			print(player.Name .. " saved successfully!")
		end
	end
end

function module.Load(player)
	if players:FindFirstChild(player.Name) then
		local status = pcall(function()
			local saveFile = game:GetService("DataStoreService"):GetDataStore("ZenithOfZeroth"):GetAsync(player.UserId)
			if saveFile then
				if saveFile[1] then
					for _,achievements in pairs(saveFile[1]) do -- Achievements
						if achievements[1] and achievements[2] and player.Achievements:FindFirstChild(achievements[1]) then
							player.Achievements[achievements[1]].Value = achievements[2]
						end
					end
				end
				if saveFile[2] then
					for _,equipped in pairs(saveFile[2]) do -- Equipments
						if equipped[1] and equipped[2] and player.Equipped:FindFirstChild(equipped[1]) then
							player.Equipped[equipped[1]].Value = equipped[2]
						end
					end
				end
				if saveFile[3] then
					for _,inventory in pairs(saveFile[3]) do -- Inventory
						if inventory[1] and inventory[2] and player.Inventory:FindFirstChild(inventory[1]) then
							player.Inventory[inventory[1]].Value = inventory[2]
						end
					end
				end
				if saveFile[4] then
					for _,stats in pairs(saveFile[4]) do -- Stats
						if stats[1] and stats[2] and player.Stats:FindFirstChild(stats[1]) then
							player.Stats[stats[1]].Value = stats[2]
						end
					end
				end
				if saveFile[5] then
					for _,basicstuff in pairs(saveFile[5]) do -- BasicStuff
						if basicstuff[1] and basicstuff[2] and player.BasicStuff:FindFirstChild(basicstuff[1]) then
							player.BasicStuff[basicstuff[1]].Value = basicstuff[2]
						end
					end
				end
				if saveFile[6] then
					for _,titles in pairs(saveFile[6]) do -- Titles
						if titles[1] and titles[2] and player.Titles:FindFirstChild(titles[1]) then
							player.Titles[titles[1]].Value = titles[2]
						end
					end
				end
				if saveFile[7] then
					for _,quests in pairs(saveFile[7]) do -- Quests
						if quests[1] and quests[2] and player.Quests:FindFirstChild(quests[1]) then
							player.Quests[quests[1]].Value = quests[2]
						end
					end
				end
				if saveFile[8] then
					for _,compeletedquests in pairs(saveFile[8]) do -- CompletedQuests
						if compeletedquests[1] and compeletedquests[2] and player.CompletedQuests:FindFirstChild(compeletedquests[1]) then
							player.CompletedQuests[compeletedquests[1]].Value = compeletedquests[2]
						end
					end
				end
			end
		end)
		if status ~= true then
			print(player.Name .. " couldn't load, retrying...")
			wait(10)
			module.Load(player)
		else
			print(player.Name .. " loaded successfully!")
		end
	end
end

function module.PlayerAdded(player)
	local function UpdateCharacter(noHeal)
		if player.Character and player.Character:FindFirstChild("Humanoid") then
		end
	end
	-- Don't mind this.
	local function CreateObject(className, parent, properties)
		local object = Instance.new(className, parent)
		for _,property in pairs(properties) do
			object[property[1]] = property[2]
		end
		return object
	end
	-- NO
		
	
	local Achievements = CreateObject("Folder", player, {
		{"Name", "Achievements"}
	})
	local BasicStuff = CreateObject("Folder", player, {
		{"Name", "BasicStuff"}
	})
	local Equipped = CreateObject("Folder", player, {
		{"Name", "Equipped"}
	})
	local Inventory = CreateObject("Folder", player, {
		{"Name", "Inventory"}
	})
	local Stats = CreateObject("Folder", player, {
		{"Name", "Stats"}
	})
	local Titles = CreateObject("Folder", player, {
		{"Name", "Titles"}
	})
	local Quests = CreateObject("Folder", player, {
		{"Name", "Quests"}
	})
	local CompletedQuests = CreateObject("Folder", player, {
		{"Name", "CompletedQuests"}
	})
	--Folders
		
	CreateObject("IntValue", player, {
		{"Name", "InventoryLimit"},
		{"Value", 40}
	})
	CreateObject("IntValue", player, {
		{"Name", "InventoryCurrent"},
		{"Value", 0}
	})
	--Inventory Stuff
	
	local level = CreateObject("IntValue", BasicStuff, {
		{"Name", "Level"},
		{"Value", 0}
	})
	local xp = CreateObject("IntValue", BasicStuff, {
		{"Name", "XP"},
		{"Value", 0}
	})
	local xpneeded = CreateObject("IntValue", BasicStuff, {
		{"Name", "XPNeeded"},
		{"Value", 2000}
	})
	local gold = CreateObject("IntValue", BasicStuff, {
		{"Name", "Gold"},
		{"Value", 100}
	})
	--BasicStuff
	
	
	local Points = CreateObject("IntValue", Stats, {
		{"Name", "Points"},
		{"Value", 1}
	})
	local Body = CreateObject("IntValue", Stats, {
		{"Name", "Body"},
		{"Value", 1}
	})
	local Armor = CreateObject("IntValue", Stats, {
		{"Name", "Armor"},
		{"Value", 1}
	})
	local Weapon = CreateObject("IntValue", Stats, {
		{"Name", "Weapon"},
		{"Value", 1}
	})
	local Mind = CreateObject("IntValue", Stats, {
		{"Name", "Mind"},
		{"Value", 1}
	})
	--STATS
	
	
	CreateObject("StringValue", Equipped, {
		{"Name", "CurrentWeapon"},
		{"Value", "None"}
	})
	CreateObject("StringValue", Equipped, {
		{"Name", "CurrentArmor"},
		{"Value", "None"}
	})
	CreateObject("StringValue", Equipped, {
		{"Name", "CurrentHelmet"},
		{"Value", "None"}
	})
	CreateObject("StringValue", Equipped, {
		{"Name", "BackAccessory"},
		{"Value", "None"}
	})
	CreateObject("StringValue", Equipped, {
		{"Name", "Ring"},
		{"Value", "None"}
	})
	CreateObject("StringValue", Equipped, {
		{"Name", "Necklace"},
		{"Value", "None"}
	})
	CreateObject("StringValue", Equipped, {
		{"Name", "Bracelet"},
		{"Value", "None"}
	})
	--Equipments
	
	
	
local function UpdateXP()
	
	while true do
		wait(0.22)
		if xp.Value >= xpneeded.Value and level.Value < serverSettings.LevelLimit.Value then
			xp.Value = 0
			level.Value += 1
			Points.Value += serverSettings.PointsPerLevel.Value
		else
			break
		end
	end
end
	--LEVEL STUFF
	
	
	xp.Changed:Connect(UpdateXP)
	UpdateXP()
	level.Changed:Connect(function()
		UpdateCharacter()
		player.Character.Humanoid.Health = player.Character.Humanoid.MaxHealth
	end)
	--ON UPDATE STUFF
	
	module.Load(player)
	
	local tag = Instance.new("Model", player)
	tag.Name = "IsLoaded"
	--OK?
	

	local function CharacterSpawned()
		UpdateCharacter()
	print("You have been Respawned upon the Mercy of Zenith!")
	end
	
	
	if player.Character then
		CharacterSpawned()
	end
	
	
	player.CharacterAdded:Connect(CharacterSpawned)
	repeat -- Autosave every 4 minutes
		wait(240)
		module.Save(player)
	until not players:FindFirstChild(player.Name)
end

return module
2 Likes

This should do what you’re looking for – I cleaned up the CreateObject function as well, so it’s easier to add more properties you may want in the future.

local players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverScriptService = game:GetService("ServerScriptService")
local serverSettings = replicatedStorage.Stats:WaitForChild("AboutServer")
local DataStoreService = game:GetService('DataStoreService')
local DataStore = DataStoreService:GetDataStore('ZenithOfZeroth')
local module = {}

local LoadFile = {}

local Values = {
	'Achievements','Equipped','Inventory','Stats','BassicStuff','Titles','Quests','CompletedQuests'
}

local PlayerValues = {}

function module.Save(player)
	if players:FindFirstChild(player.Name) and player:FindFirstChild("IsLoaded") then
		local status, message = pcall(function()
			local SaveFile = {}
			for i,v in ipairs(Values) do
				local Folder = player:findFirstChild(v)
				if Folder then
					for i,v in ipairs(Folder:GetChildren()) do
						local Value = v
						if Value:IsA('ValueBase') then
							table.insert(SaveFile,{
								Value.Name,
								Value.Value,
							})
						end
					end
				end
			end
			DataStore:SetAsync(player.UserId, SaveFile)
		end)
		if status ~= true then
			print(player.Name .. " couldn't save, retrying... \n" .. message)
			module.Save(player)
		else
			print(player.Name .. " saved successfully!")
		end
	end
end

function module.Load(player)
	if players:FindFirstChild(player.Name) then
		local status,errormsg = pcall(function()
			local saveFile = DataStore:GetAsync(player.UserId)
			if saveFile then
				for i,v in ipairs(saveFile) do
					local Value = PlayerValues[player.Name][v[1]]
					if Value then
						Value.Value = v[2]
					end
				end
			end
		end)
		if status ~= true then
			if player.LoadAttempts.Value < 5 then
				print(errormsg)
				player.LoadAttempts.Value = player.LoadAttempts.Value+1
				print(player.Name .. " couldn't load, retrying...")
				module.Load(player)
			else
				print('Error loading data')
			end
		else
			print(player.Name .. " loaded successfully!")
		end
	end
end


-- MAKE SURE YOU CALL THIS WHEN THEY LEAVE THE GAME SO IT CLEANS UP THEIR VALUES
function module.PlayerRemoved(player)
	PlayerValues[player.Name] = nil
end

function module.PlayerAdded(player)
	PlayerValues[player.Name] = {}
	local function UpdateCharacter(noHeal)
		if player.Character and player.Character:FindFirstChild("Humanoid") then
		end
	end
	-- Don't mind this.
	local function CreateObject(className, properties)
		local object = Instance.new(className)
		for property,value in pairs(properties) do
			object[property] = value
		end
		if object:IsA('ValueBase') then
			PlayerValues[player.Name][properties.Name] = object
		end
		return object
	end
	
	-- NO
	-- THIS IS SO WE DON'T EXHAUST THE DATASTORE LIMIT KEEP THIS
	CreateObject("IntValue",{
		Parent = player,
		Name = 'LoadAttempts',
	})
	
	local Achievements = CreateObject("Folder",{
		Parent = player,
		Name = 'Achievements',
	})
	local BasicStuff = CreateObject("Folder",{
		Parent = player,
		Name = 'BasicStuff',
	})
	local Equipped = CreateObject("Folder", {
		Parent = player,
		Name = 'Equipped',
	})
	local Inventory = CreateObject("Folder", {
		Parent = player,
		Name = 'Inventory',
	})
	local Stats = CreateObject("Folder", {
		Parent = player,
		Name = 'Stats',
	})
	local Titles = CreateObject("Folder", {
		Parent = player,
		Name = 'Titles',
	})
	local Quests = CreateObject("Folder", {
		Parent = player,
		Name = 'Quests',
	})
	local CompletedQuests = CreateObject("Folder", {
		Parent = player,
		Name = 'CompletedQuests',
	})
	----Folders

	CreateObject("IntValue", {
		Parent = player,
		Name = 'InventoryLimit',
		Value = 40,
	})
	CreateObject("IntValue", {
		Parent = player,
		Name = 'InventoryCurrent',
		Value = 0,
	})
	--Inventory Stuff

	local level = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'Level',
		Value = 0,
	})
	local xp = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'XP',
		Value = 0,
	})
	local xpneeded = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'XPNeeded',
		Value = 2000,
	})
	local gold = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'Gold',
		Value = 100,
	})
	----BasicStuff


	local Points = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Points',
		Value = 1,
	})
	local Body = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Body',
		Value = 1,
	})
	local Armor = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Armor',
		Value = 1,
	})
	local Weapon = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Weapon',
		Value = 1,
	})
	local Mind = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Mind',
		Value = 1,
	})
	----STATS


	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'CurrentWeapon',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'CurrentArmor',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'CurrentHelmet',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'BackAccessory',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'Ring',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'Necklace',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'Bracelet',
		Value = 'None',
	})
	--Equipments



	local function UpdateXP()

		while true do
			wait(0.22)
			if xp.Value >= xpneeded.Value and level.Value < serverSettings.LevelLimit.Value then
				xp.Value = 0
				level.Value += 1
				Points.Value += serverSettings.PointsPerLevel.Value
			else
				break
			end
		end
	end
	--LEVEL STUFF


	xp.Changed:Connect(UpdateXP)
	--UpdateXP()
	level.Changed:Connect(function()
		UpdateCharacter()
		player.Character.Humanoid.Health = player.Character.Humanoid.MaxHealth
	end)
	--ON UPDATE STUFF

	module.Load(player)

	local tag = Instance.new("Model", player)
	tag.Name = "IsLoaded"
	--OK?


	local function CharacterSpawned()
		UpdateCharacter()
		print("You have been Respawned upon the Mercy of Zenith!")
	end


	if player.Character then
		CharacterSpawned()
	end

	player.CharacterAdded:Connect(CharacterSpawned)
	repeat -- Autosave every 4 minutes
		wait(240)
		module.Save(player)
	until not players:FindFirstChild(player.Name)
end

return module

If any issues, let me know. :slight_smile:

2 Likes

it doesn’t seem to save i think… :frowning:
tested again with old data: it doesn’t seem to load too :frowning:o

ooh wait it was becuase of another script. thx

1 Like

Sure thing! So it appears to load and save properly now?

2 Likes

it saves and loads properly but when i add a value from outside like this:
image

it doesn’t load to game, only values from script loads
image

do i have to add items in another way or?

1 Like

I’m sorry, I don’t know what you’re trying to say. When you add a value from outside?

I mean like, adding item from quest or mob drop :c
I mean it saves but doesn’t load

1 Like

Aah… That’s because we store the values in PlayerValues and check to see if value exists to save the corresponding Value of said value. This should fix that issue:

local players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverScriptService = game:GetService("ServerScriptService")
local serverSettings = replicatedStorage.Stats:WaitForChild("AboutServer")
local DataStoreService = game:GetService('DataStoreService')
local DataStore = DataStoreService:GetDataStore('ZenithOfZeroth')
local module = {}

local LoadFile = {}

local Values = {
	'Achievements','Equipped','Inventory','Stats','BassicStuff','Titles','Quests','CompletedQuests'
}

local PlayerValues = {}

function module.Save(player)
	if players:FindFirstChild(player.Name) and player:FindFirstChild("IsLoaded") then
		local status, message = pcall(function()
			local SaveFile = {}
			for i,v in ipairs(Values) do
				local Folder = player:findFirstChild(v)
				if Folder then
					for i,v in ipairs(Folder:GetChildren()) do
						local Value = v
						if Value:IsA('ValueBase') then
							table.insert(SaveFile,{
								Value.Name,
								Value.Value,
							})
						end
					end
				end
			end
			print(game:GetService('HttpService'):JSONEncode(SaveFile))
			DataStore:SetAsync(player.UserId, SaveFile)
		end)
		if status ~= true then
			print(player.Name .. " couldn't save, retrying... \n" .. message)
			module.Save(player)
		else
			print(player.Name .. " saved successfully!")
		end
	end
end

function module.Load(player)
	if players:FindFirstChild(player.Name) then
		local status,errormsg = pcall(function()
			local SaveFile = DataStore:GetAsync(player.UserId)
			if SaveFile then
				for i,v in ipairs(SaveFile) do
					local Value = PlayerValues[player.Name][v[1]]
					if Value then
						Value.Value = v[2]
					end
				end
			end
		end)
		if status ~= true then
			if player.LoadAttempts.Value < 5 then
				print(errormsg)
				player.LoadAttempts.Value = player.LoadAttempts.Value+1
				print(player.Name .. " couldn't load, retrying...")
				module.Load(player)
			else
				print('Error loading data')
			end
		else
			print(player.Name .. " loaded successfully!")
		end
	end
end


-- MAKE SURE YOU CALL THIS WHEN THEY LEAVE THE GAME SO IT CLEANS UP THEIR VALUES
function module.PlayerRemoved(player)
	PlayerValues[player.Name] = nil
end

function module.PlayerAdded(player)
	PlayerValues[player.Name] = {}
	local function UpdateCharacter(noHeal)
		if player.Character and player.Character:FindFirstChild("Humanoid") then
		end
	end
	-- Don't mind this.
	local function CreateObject(className, properties)
		local object = Instance.new(className)
		for property,value in pairs(properties) do
			object[property] = value
		end
		if object:IsA('ValueBase') then
			PlayerValues[player.Name][properties.Name] = object
		end
		return object
	end
	
	player.DescendantAdded:Connect(function(object)
		if object:IsA('ValueBase') then
			print('added')
			PlayerValues[player.Name][object.Name] = object
		end
	end)
	-- NO
	-- THIS IS SO WE DON'T EXHAUST THE DATASTORE LIMIT KEEP THIS
	CreateObject("IntValue",{
		Parent = player,
		Name = 'LoadAttempts',
	})

	local Achievements = CreateObject("Folder",{
		Parent = player,
		Name = 'Achievements',
	})
	local BasicStuff = CreateObject("Folder",{
		Parent = player,
		Name = 'BasicStuff',
	})
	local Equipped = CreateObject("Folder", {
		Parent = player,
		Name = 'Equipped',
	})
	local Inventory = CreateObject("Folder", {
		Parent = player,
		Name = 'Inventory',
	})
	local Stats = CreateObject("Folder", {
		Parent = player,
		Name = 'Stats',
	})
	local Titles = CreateObject("Folder", {
		Parent = player,
		Name = 'Titles',
	})
	local Quests = CreateObject("Folder", {
		Parent = player,
		Name = 'Quests',
	})
	local CompletedQuests = CreateObject("Folder", {
		Parent = player,
		Name = 'CompletedQuests',
	})
	----Folders

	CreateObject("IntValue", {
		Parent = player,
		Name = 'InventoryLimit',
		Value = 40,
	})
	CreateObject("IntValue", {
		Parent = player,
		Name = 'InventoryCurrent',
		Value = 0,
	})
	--Inventory Stuff

	local level = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'Level',
		Value = 0,
	})
	local xp = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'XP',
		Value = 0,
	})
	local xpneeded = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'XPNeeded',
		Value = 2000,
	})
	local gold = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'Gold',
		Value = 100,
	})
	----BasicStuff


	local Points = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Points',
		Value = 1,
	})
	local Body = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Body',
		Value = 1,
	})
	local Armor = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Armor',
		Value = 1,
	})
	local Weapon = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Weapon',
		Value = 1,
	})
	local Mind = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Mind',
		Value = 1,
	})
	----STATS


	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'CurrentWeapon',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'CurrentArmor',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'CurrentHelmet',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'BackAccessory',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'Ring',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'Necklace',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'Bracelet',
		Value = 'None',
	})
	--Equipments



	local function UpdateXP()

		while true do
			wait(0.22)
			if xp.Value >= xpneeded.Value and level.Value < serverSettings.LevelLimit.Value then
				xp.Value = 0
				level.Value += 1
				Points.Value += serverSettings.PointsPerLevel.Value
			else
				break
			end
		end
	end
	--LEVEL STUFF


	xp.Changed:Connect(UpdateXP)
	UpdateXP()
	level.Changed:Connect(function()
		UpdateCharacter()
		player.Character.Humanoid.Health = player.Character.Humanoid.MaxHealth
	end)
	--ON UPDATE STUFF

	module.Load(player)

	local tag = Instance.new("Model", player)
	tag.Name = "IsLoaded"
	--OK?


	local function CharacterSpawned()
		UpdateCharacter()
		print("You have been Respawned upon the Mercy of Zenith!")
	end


	if player.Character then
		CharacterSpawned()
	end

	player.CharacterAdded:Connect(CharacterSpawned)
	repeat -- Autosave every 4 minutes
		wait(240)
		module.Save(player)
	until not players:FindFirstChild(player.Name)
end

return module

it saves the added thing but not loads what i add to Inventory or Quests etc. :frowning:

Added:
image


After rejoin:
image

1 Like

Try changing the Load() and Save() functions to this and paste what the output is please:

function module.Save(player)
	if players:FindFirstChild(player.Name) and player:FindFirstChild("IsLoaded") then
		local status, message = pcall(function()
			local SaveFile = {}
			for i,v in ipairs(Values) do
				local Folder = player:findFirstChild(v)
				if Folder then
					for i,v in ipairs(Folder:GetChildren()) do
						local Value = v
						if Value:IsA('ValueBase') then
							table.insert(SaveFile,{
								Value.Name,
								Value.Value,
							})
						end
					end
				end
			end
			print(game:GetService('HttpService'):JSONEncode(SaveFile))
			DataStore:SetAsync(player.UserId, SaveFile)
		end)
		if status ~= true then
			print(player.Name .. " couldn't save, retrying... \n" .. message)
			module.Save(player)
		else
			print(player.Name .. " saved successfully!")
		end
	end
end

function module.Load(player)
	if players:FindFirstChild(player.Name) then
		local status,errormsg = pcall(function()
			local SaveFile = DataStore:GetAsync(player.UserId)
			if SaveFile then
				print(game:GetService('HttpService'):JSONEncode(SaveFile))
				for i,v in ipairs(SaveFile) do
					local Value = PlayerValues[player.Name][v[1]]
					if Value then
						Value.Value = v[2]
					end
				end
			end
		end)
		if status ~= true then
			if player.LoadAttempts.Value < 5 then
				print(errormsg)
				player.LoadAttempts.Value = player.LoadAttempts.Value+1
				print(player.Name .. " couldn't load, retrying...")
				module.Load(player)
			else
				print('Error loading data')
			end
		else
			print(player.Name .. " loaded successfully!")
		end
	end
end
2 Likes

1st Join and leave


2nd Join


But Not loaded
image

1 Like

The issue is not that it’s not loading the data itself, it’s that you’re wanting it to create new instances based on if they don’t currently exist in the folders / player.

Personally, I would go about writing all of this differently, but if you want it to create instances if they don’t currently exist, we need to have a dictionary of the values you would be creating and their corresponding parent. Something like this:

local Example = {
	['ValueName'] = 'ParentName',
}

Is Inventory the only folder you’re adding values to that are created on run-time?

1 Like

I plan to add Quests, CompletedQuests, Achievements, Inventory and Titles

I plan to add them when mob killed or when an achievement achieved etc.

1 Like

Hmm… So like I said, I would go about writing this a different way, but we can still set it up to work as it is. I’ll provide the updated code that should work as you’re intending to create instances – give me a few. :slight_smile:

2 Likes

Like Killing 100 Goblins or Achieving 100 Body stats
or mob drop and quest reward etc.

1 Like

Okay, so here’s what you need to get it to create instances which then will also load with data that is saved:

llocal players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverScriptService = game:GetService("ServerScriptService")
local serverSettings = replicatedStorage.Stats:WaitForChild("AboutServer")
local DataStoreService = game:GetService('DataStoreService')
local DataStore = DataStoreService:GetDataStore('ZenithOfZeroth')
local module = {}

local LoadFile = {}

local Values = {
	'Achievements','Equipped','Inventory','Stats','BassicStuff','Titles','Quests','CompletedQuests'
}

local InstancesToCreate = {
	{Name = 'Apple', Type = 'IntValue', Parent = 'Inventory'},
	{Name = 'Pear', Type = 'IntValue', Parent = 'Inventory'},
	{Name = 'Orange', Type = 'IntValue', Parent = 'Inventory'},
	{Name = 'TESTITEM', Type = 'StringValue', Parent = 'Inventory'}
}

local PlayerValues = {}

function module.Save(player)
	if players:FindFirstChild(player.Name) and player:FindFirstChild("IsLoaded") then
		local status, message = pcall(function()
			local SaveFile = {}
			for i,v in ipairs(Values) do
				local Folder = player:findFirstChild(v)
				if Folder then
					for i,v in ipairs(Folder:GetChildren()) do
						local Value = v
						if Value:IsA('ValueBase') then
							table.insert(SaveFile,{
								Value.Name,
								Value.Value,
							})
						end
					end
				end
			end
			print(game:GetService('HttpService'):JSONEncode(SaveFile))
			DataStore:SetAsync(player.UserId, SaveFile)
		end)
		if status ~= true then
			print(player.Name .. " couldn't save, retrying... \n" .. message)
			module.Save(player)
		else
			print(player.Name .. " saved successfully!")
		end
	end
end

function module.Load(player)
	if players:FindFirstChild(player.Name) then
		local status,errormsg = pcall(function()
			local SaveFile = DataStore:GetAsync(player.UserId)
			if SaveFile then
				print(game:GetService('HttpService'):JSONEncode(SaveFile))
				for i,v in ipairs(SaveFile) do
					local Value = PlayerValues[player.Name][v[1]]
					if Value then
						Value.Value = v[2]
					end
				end
			end
		end)
		if status ~= true then
			if player.LoadAttempts.Value < 5 then
				print(errormsg)
				player.LoadAttempts.Value = player.LoadAttempts.Value+1
				print(player.Name .. " couldn't load, retrying...")
				module.Load(player)
			else
				print('Error loading data')
			end
		else
			print(player.Name .. " loaded successfully!")
		end
	end
end


-- MAKE SURE YOU CALL THIS WHEN THEY LEAVE THE GAME SO IT CLEANS UP THEIR VALUES
function module.PlayerRemoved(player)
	PlayerValues[player.Name] = nil
end

function module.PlayerAdded(player)
	PlayerValues[player.Name] = {}
	local function UpdateCharacter(noHeal)
		if player.Character and player.Character:FindFirstChild("Humanoid") then
		end
	end
	-- Don't mind this.
	local function CreateObject(className, properties)
		local object = Instance.new(className)
		for property,value in pairs(properties) do
			object[property] = value
		end
		if object:IsA('ValueBase') then
			PlayerValues[player.Name][properties.Name] = object
		end
		return object
	end
	
	player.DescendantAdded:Connect(function(object)
		if object:IsA('ValueBase') then
			PlayerValues[player.Name][object.Name] = object
		end
	end)
	-- NO
	-- THIS IS SO WE DON'T EXHAUST THE DATASTORE LIMIT KEEP THIS
	CreateObject("IntValue",{
		Parent = player,
		Name = 'LoadAttempts',
	})

	local Achievements = CreateObject("Folder",{
		Parent = player,
		Name = 'Achievements',
	})
	local BasicStuff = CreateObject("Folder",{
		Parent = player,
		Name = 'BasicStuff',
	})
	local Equipped = CreateObject("Folder", {
		Parent = player,
		Name = 'Equipped',
	})
	local Inventory = CreateObject("Folder", {
		Parent = player,
		Name = 'Inventory',
	})
	local Stats = CreateObject("Folder", {
		Parent = player,
		Name = 'Stats',
	})
	local Titles = CreateObject("Folder", {
		Parent = player,
		Name = 'Titles',
	})
	local Quests = CreateObject("Folder", {
		Parent = player,
		Name = 'Quests',
	})
	local CompletedQuests = CreateObject("Folder", {
		Parent = player,
		Name = 'CompletedQuests',
	})
	----Folders

	CreateObject("IntValue", {
		Parent = player,
		Name = 'InventoryLimit',
		Value = 40,
	})
	CreateObject("IntValue", {
		Parent = player,
		Name = 'InventoryCurrent',
		Value = 0,
	})
	--Inventory Stuff

	local level = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'Level',
		Value = 0,
	})
	local xp = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'XP',
		Value = 0,
	})
	local xpneeded = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'XPNeeded',
		Value = 2000,
	})
	local gold = CreateObject("IntValue", {
		Parent = BasicStuff,
		Name = 'Gold',
		Value = 100,
	})
	----BasicStuff


	local Points = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Points',
		Value = 1,
	})
	local Body = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Body',
		Value = 1,
	})
	local Armor = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Armor',
		Value = 1,
	})
	local Weapon = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Weapon',
		Value = 1,
	})
	local Mind = CreateObject("IntValue", {
		Parent = Stats,
		Name = 'Mind',
		Value = 1,
	})
	----STATS


	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'CurrentWeapon',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'CurrentArmor',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'CurrentHelmet',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'BackAccessory',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'Ring',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'Necklace',
		Value = 'None',
	})
	CreateObject("StringValue", {
		Parent = Equipped,
		Name = 'Bracelet',
		Value = 'None',
	})
	--Equipments

	for i,v in ipairs(InstancesToCreate) do
		CreateObject(v.Type,{
			Name = v.Name,
			Parent = player:findFirstChild(v.Parent)
		})
	end

	local function UpdateXP()

		while true do
			wait(0.22)
			if xp.Value >= xpneeded.Value and level.Value < serverSettings.LevelLimit.Value then
				xp.Value = 0
				level.Value += 1
				Points.Value += serverSettings.PointsPerLevel.Value
			else
				break
			end
		end
	end
	--LEVEL STUFF


	xp.Changed:Connect(UpdateXP)
	UpdateXP()
	level.Changed:Connect(function()
		UpdateCharacter()
		player.Character.Humanoid.Health = player.Character.Humanoid.MaxHealth
	end)
	--ON UPDATE STUFF

	module.Load(player)

	local tag = Instance.new("Model", player)
	tag.Name = "IsLoaded"
	--OK?


	local function CharacterSpawned()
		UpdateCharacter()
		print("You have been Respawned upon the Mercy of Zenith!")
	end


	if player.Character then
		CharacterSpawned()
	end

	player.CharacterAdded:Connect(CharacterSpawned)
	repeat -- Autosave every 4 minutes
		wait(240)
		module.Save(player)
	until not players:FindFirstChild(player.Name)
end

return module

As you can see with the the following table, you will need to populate it with information about the instances you need created:

local InstancesToCreate = {
	{Name = 'Apple', Type = 'IntValue', Parent = 'Inventory'},
	{Name = 'Pear', Type = 'IntValue', Parent = 'Inventory'},
	{Name = 'Orange', Type = 'IntValue', Parent = 'Inventory'},
	{Name = 'TESTITEM', Type = 'StringValue', Parent = 'Inventory'}
}

Anyways, good luck and hope this helped! :slight_smile:

1 Like

Okay, so if you wanted where you don’t have to add to that table of items and just have it do it all automatically, I set this up so that it’ll save the parent location, type of instance, name, and value that way it should allow you to add anything to the folders and save / load properly.

local players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local serverScriptService = game:GetService("ServerScriptService")
local serverSettings = replicatedStorage.Stats:WaitForChild("AboutServer")
local DataStoreService = game:GetService('DataStoreService')
local DataStore = DataStoreService:GetDataStore('ZenithOfZeroth')
local module = {}

local LoadFile = {}

local Values = {
	'Achievements','Equipped','Inventory','Stats','BassicStuff','Titles','Quests','CompletedQuests'
}

local PlayerValues = {}

local function CreateObject(player, className, properties)
	local object = Instance.new(className)
	for property,value in pairs(properties) do
		object[property] = value
	end
	if object:IsA('ValueBase') then
		PlayerValues[player.Name][properties.Name] = object
	end
	return object
end

function module.Save(player)
	if players:FindFirstChild(player.Name) and player:FindFirstChild("IsLoaded") then
		local status, message = pcall(function()
			local SaveFile = {}
			for i,v in ipairs(Values) do
				local Folder = player:findFirstChild(v)
				if Folder then
					for i,v in ipairs(Folder:GetChildren()) do
						local Value = v
						if Value:IsA('ValueBase') then
							table.insert(SaveFile,{
								Value.Name,
								Value.Value,
								Value.ClassName,
								Value.Parent.Name,
							})
						end
					end
				end
			end
			print(game:GetService('HttpService'):JSONEncode(SaveFile))
			DataStore:SetAsync(player.UserId, SaveFile)
		end)
		if status ~= true then
			print(player.Name .. " couldn't save, retrying... \n" .. message)
			module.Save(player)
		else
			print(player.Name .. " saved successfully!")
		end
	end
end

function module.Load(player)
	if players:FindFirstChild(player.Name) then
		local status,errormsg = pcall(function()
			local SaveFile = DataStore:GetAsync(player.UserId)
			if SaveFile then
				print(game:GetService('HttpService'):JSONEncode(SaveFile))
				for i,v in ipairs(SaveFile) do
					local Value = PlayerValues[player.Name][v[1]]
					if not Value then
						local val = CreateObject(player,v[3],{
							Parent = player:findFirstChild(v[4]),
							Name = v[1],
						})
						PlayerValues[player.Name][v[1]] = val
						Value = val
					end
					
					Value.Value = v[2]
					
				end
			end
		end)
		if status ~= true then
			if player.LoadAttempts.Value < 5 then
				print(errormsg)
				player.LoadAttempts.Value = player.LoadAttempts.Value+1
				print(player.Name .. " couldn't load, retrying...")
				module.Load(player)
			else
				print('Error loading data')
			end
		else
			print(player.Name .. " loaded successfully!")
		end
	end
end


-- MAKE SURE YOU CALL THIS WHEN THEY LEAVE THE GAME SO IT CLEANS UP THEIR VALUES
function module.PlayerRemoved(player)
	PlayerValues[player.Name] = nil
end

function module.PlayerAdded(player)
	PlayerValues[player.Name] = {}
	local function UpdateCharacter(noHeal)
		if player.Character and player.Character:FindFirstChild("Humanoid") then
		end
	end
	-- Don't mind this.
	
	player.DescendantAdded:Connect(function(object)
		if object:IsA('ValueBase') then
			PlayerValues[player.Name][object.Name] = object
		end
	end)
	-- NO
	-- THIS IS SO WE DON'T EXHAUST THE DATASTORE LIMIT KEEP THIS
	CreateObject(player,"IntValue",{
		Parent = player,
		Name = 'LoadAttempts',
	})

	local Achievements = CreateObject(player,"Folder",{
		Parent = player,
		Name = 'Achievements',
	})
	local BasicStuff = CreateObject(player,"Folder",{
		Parent = player,
		Name = 'BasicStuff',
	})
	local Equipped = CreateObject(player,"Folder", {
		Parent = player,
		Name = 'Equipped',
	})
	local Inventory = CreateObject(player,"Folder", {
		Parent = player,
		Name = 'Inventory',
	})
	local Stats = CreateObject(player,"Folder", {
		Parent = player,
		Name = 'Stats',
	})
	local Titles = CreateObject(player,"Folder", {
		Parent = player,
		Name = 'Titles',
	})
	local Quests = CreateObject(player,"Folder", {
		Parent = player,
		Name = 'Quests',
	})
	local CompletedQuests = CreateObject(player,"Folder", {
		Parent = player,
		Name = 'CompletedQuests',
	})
	----Folders

	CreateObject(player,"IntValue", {
		Parent = player,
		Name = 'InventoryLimit',
		Value = 40,
	})
	CreateObject(player,"IntValue", {
		Parent = player,
		Name = 'InventoryCurrent',
		Value = 0,
	})
	--Inventory Stuff

	local level = CreateObject(player,"IntValue", {
		Parent = BasicStuff,
		Name = 'Level',
		Value = 0,
	})
	local xp = CreateObject(player,"IntValue", {
		Parent = BasicStuff,
		Name = 'XP',
		Value = 0,
	})
	local xpneeded = CreateObject(player,"IntValue", {
		Parent = BasicStuff,
		Name = 'XPNeeded',
		Value = 2000,
	})
	local gold = CreateObject(player,"IntValue", {
		Parent = BasicStuff,
		Name = 'Gold',
		Value = 100,
	})
	----BasicStuff


	local Points = CreateObject(player,"IntValue", {
		Parent = Stats,
		Name = 'Points',
		Value = 1,
	})
	local Body = CreateObject(player,"IntValue", {
		Parent = Stats,
		Name = 'Body',
		Value = 1,
	})
	local Armor = CreateObject(player,"IntValue", {
		Parent = Stats,
		Name = 'Armor',
		Value = 1,
	})
	local Weapon = CreateObject(player,"IntValue", {
		Parent = Stats,
		Name = 'Weapon',
		Value = 1,
	})
	local Mind = CreateObject(player,"IntValue", {
		Parent = Stats,
		Name = 'Mind',
		Value = 1,
	})
	----STATS


	CreateObject(player,"StringValue", {
		Parent = Equipped,
		Name = 'CurrentWeapon',
		Value = 'None',
	})
	CreateObject(player,"StringValue", {
		Parent = Equipped,
		Name = 'CurrentArmor',
		Value = 'None',
	})
	CreateObject(player,"StringValue", {
		Parent = Equipped,
		Name = 'CurrentHelmet',
		Value = 'None',
	})
	CreateObject(player,"StringValue", {
		Parent = Equipped,
		Name = 'BackAccessory',
		Value = 'None',
	})
	CreateObject(player,"StringValue", {
		Parent = Equipped,
		Name = 'Ring',
		Value = 'None',
	})
	CreateObject(player,"StringValue", {
		Parent = Equipped,
		Name = 'Necklace',
		Value = 'None',
	})
	CreateObject(player,"StringValue", {
		Parent = Equipped,
		Name = 'Bracelet',
		Value = 'None',
	})
	--Equipments

	local function UpdateXP()

		while true do
			wait(0.22)
			if xp.Value >= xpneeded.Value and level.Value < serverSettings.LevelLimit.Value then
				xp.Value = 0
				level.Value += 1
				Points.Value += serverSettings.PointsPerLevel.Value
			else
				break
			end
		end
	end
	--LEVEL STUFF


	xp.Changed:Connect(UpdateXP)
	UpdateXP()
	level.Changed:Connect(function()
		UpdateCharacter()
		player.Character.Humanoid.Health = player.Character.Humanoid.MaxHealth
	end)
	--ON UPDATE STUFF

	module.Load(player)

	local tag = Instance.new("Model", player)
	tag.Name = "IsLoaded"
	--OK?


	local function CharacterSpawned()
		UpdateCharacter()
		print("You have been Respawned upon the Mercy of Zenith!")
	end


	if player.Character then
		CharacterSpawned()
	end

	player.CharacterAdded:Connect(CharacterSpawned)
	repeat -- Autosave every 4 minutes
		wait(240)
		module.Save(player)
	until not players:FindFirstChild(player.Name)
end


return module

Glad I could help! :slight_smile:

2 Likes

YES! THIS IS WHAT I HAVE BEEN SEARCHING FOR! Thank you so much!

2 Likes

Haha, no worries. :slight_smile: Hope it’ll work for you.

2 Likes

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