Saving folders content with Datastore2

Ah, my old script is too old and broken :d but I can say you can make it something like this

I don’t really have time to make a full tutorial from 0 so I have given my scripts

Save
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
Load
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

For Profile Service I recommend watching all the tutorials they have and Make a mix of them :d

First get the Profile Service:

Make a Folder under ServerScriptService, Put ProfileService under it
image

and Make another folder
image

I prefer Seperating them to edit it easly

Lets start with easiest:
Template is the Module script where you put your Values to use inside profile:

Template
local module = {
	Gold = 0,
	Level = 1,
	Rebirth = 0,

	XP = 0,
	XPNeeded = 50,

	LevelLimit = 100,

	AttackSpeed = 2,
	DamageBoost = 1,
	RewardsBoost = 1,
	
	UpgradesDone = 0,

	Damage = 15,

	XPBoost = 1,
	GoldBoost = 1,

	TotalGoldEarned = 0,
	TotalBlocksMined = 0,

	PickaxeEquipped = "LvL. 1 Pickaxe",

	GiftGold = 0,
	GiftAttackSpeed = 0,
	GiftDamageBoost = 0,
	GiftRewardsBoost = 0,
	GiftXPBoost = 0,
	GiftGoldBoost = 0
	
}

return module

Then next is Manager!

Manager
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TownLevel = ReplicatedStorage:WaitForChild("TownLevel")
local CurrentTownLevel = TownLevel:WaitForChild("CurrentTownLevel")
local EXPBOOST = CurrentTownLevel:WaitForChild("EXPBOOST")
local GOLDBOOST = CurrentTownLevel:WaitForChild("GOLDBOOST")

local module = {}

module.Profiles = {}


--- LeaderStats STUFF


function module:AddGold(player, amount)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    if not profile then return end

    profile.Data.Gold += (amount * profile.Data.GoldBoost) * GOLDBOOST.Value
    player.leaderstats.Gold.Value = profile.Data.Gold
end

function module:GiftGold(player, NameOfValue, AmountOfValue, target)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    if not profile then return end

	local Players = game:GetService("Players")
	
	if target == player.Name then
		warn("Bro trying to put Stat from his 1 pocket to another")
	else
		if Players:FindFirstChild(target) then
			local RealTarget = Players:FindFirstChild(target)
			local Gifts = RealTarget:WaitForChild("Gifts")
			local Gold = Gifts:WaitForChild("GiftGold")
			local AttackSpeed = Gifts:WaitForChild("GiftAttackSpeed")
			local DamageBoost = Gifts:WaitForChild("GiftDamageBoost")
			local RewardsBoost = Gifts:WaitForChild("GiftRewardsBoost")
			local XPBoost = Gifts:WaitForChild("GiftXPBoost")
			local GoldBoost = Gifts:WaitForChild("GiftGoldBoost")

			if AmountOfValue >= 1 then
				if profile.Data[NameOfValue] - AmountOfValue >= 0 then
					if NameOfValue == "Gold" then
						
						profile.Data[NameOfValue] -= AmountOfValue
						Gifts["Gift"..NameOfValue].Value += AmountOfValue
						
						player.leaderstats.Gold.Value = profile.Data.Gold

						print("Successfully Sent "..AmountOfValue.." Amount Of Gold to: "..RealTarget.Name)

					elseif NameOfValue == "AttackSpeed" or
					       NameOfValue == "DamageBoost" or
					       NameOfValue == "RewardsBoost" or
					       NameOfValue == "XPBoost" or
					       NameOfValue == "GoldBoost" then
			
						profile.Data[NameOfValue] -= AmountOfValue
						Gifts["Gift"..NameOfValue].Value += AmountOfValue

						player.Stats[NameOfValue].Value = profile.Data[NameOfValue]
			
						print("Successfully Sent "..AmountOfValue.." Amount Of "..NameOfValue.." to: "..RealTarget.Name)

					else
						warn("Value Not Found: ", NameOfValue)
					end
				else
					warn("You can't go Negative Stats! Stat Used: ", NameOfValue)
				end
			elseif AmountOfValue == 0 then
				warn("Can't Send 0, its pointless")
			elseif AmountOfValue < 0 then
				warn("You trying to Steal from Player?")
			end
		else
			warn("Target not Found ", target)
		end
	end

end

function module:ControlGifts(player)
	local Profiles = module.Profiles
    local profile = Profiles[player]
    if not profile then return end
	
	local function UpdateGiftGold()
		
		if player.Gifts.GiftGold.Value > 0 then
		profile.Data.Gold += player.Gifts.GiftGold.Value
		player.leaderstats.Gold.Value = profile.Data.Gold
		player.Gifts.GiftGold.Value -= player.Gifts.GiftGold.Value

		else
			return false
		end
	end

	local function UpdateGiftAttackSpeed()
		
		if player.Gifts.GiftAttackSpeed.Value > 0 then
		profile.Data.AttackSpeed += player.Gifts.GiftAttackSpeed.Value
		player.Stats.AttackSpeed.Value = profile.Data.AttackSpeed
		player.Gifts.GiftAttackSpeed.Value -= player.Gifts.GiftAttackSpeed.Value

		else
			return false
		end
	end

	local function UpdateGiftDamageBoost()
		
		if player.Gifts.GiftDamageBoost.Value > 0 then
		profile.Data.DamageBoost += player.Gifts.GiftDamageBoost.Value
		player.Stats.DamageBoost.Value = profile.Data.DamageBoost
		player.Gifts.GiftDamageBoost.Value -= player.Gifts.GiftDamageBoost.Value

		else
			return false
		end
	end

	local function UpdateGiftRewardsBoost()
		
		if player.Gifts.GiftRewardsBoost.Value > 0 then
		profile.Data.RewardsBoost += player.Gifts.GiftRewardsBoost.Value
		player.Stats.RewardsBoost.Value = profile.Data.RewardsBoost
		player.Gifts.GiftRewardsBoost.Value -= player.Gifts.GiftRewardsBoost.Value

		else
			return false
		end
	end

	local function UpdateGiftXPBoost()
		
		if player.Gifts.GiftXPBoost.Value > 0 then
		profile.Data.XPBoost += player.Gifts.GiftXPBoost.Value
		player.Stats.XPBoost.Value = profile.Data.XPBoost
		player.Gifts.GiftXPBoost.Value -= player.Gifts.GiftXPBoost.Value
		
		else
			return false
		end
	end

	local function UpdateGiftGoldBoost()
		
		if player.Gifts.GiftGoldBoost.Value > 0 then
		profile.Data.GoldBoost += player.Gifts.GiftGoldBoost.Value
		player.Stats.GoldBoost.Value = profile.Data.GoldBoost
		player.Gifts.GiftGoldBoost.Value -= player.Gifts.GiftGoldBoost.Value

		else
			return false
		end
	end

	local function UpdateGiftDataToProfile()
		profile.Data.GiftGold = player.Gifts.GiftGold.Value
		profile.Data.GiftAttackSpeed = player.Gifts.GiftAttackSpeed.Value
		profile.Data.GiftDamageBoost = player.Gifts.GiftDamageBoost.Value
		profile.Data.GiftRewardsBoost = player.Gifts.GiftRewardsBoost.Value
		profile.Data.GiftXPBoost = player.Gifts.GiftXPBoost.Value
		profile.Data.GiftGoldBoost = player.Gifts.GiftGoldBoost.Value

		UpdateGiftGold()
		UpdateGiftAttackSpeed()
		UpdateGiftDamageBoost()
		UpdateGiftRewardsBoost()
		UpdateGiftXPBoost()
		UpdateGiftGoldBoost()
	end

	UpdateGiftDataToProfile()

end

function module:AddLevel(player, amount)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    if not profile then return end

    profile.Data.Level += amount
    player.leaderstats.Level.Value = profile.Data.Level
end

function module:AddRebirth(player)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    if not profile then return end

if player.leaderstats.Level.Value == player.Stats.LevelLimit.Value then

    profile.Data.Rebirth += 1
	player.leaderstats.Rebirth.Value = profile.Data.Rebirth

	local RebirthStatMultipler = 0.5

	profile.Data.GoldBoost = 2.5 + (0.5 * player.leaderstats.Rebirth.Value)
	profile.Data.XPBoost = 2.5 + (0.5 * player.leaderstats.Rebirth.Value)
	profile.Data.DamageBoost = 2.5 + (0.5 * player.leaderstats.Rebirth.Value)
	profile.Data.RewardsBoost = 2.5 + (0.5 * player.leaderstats.Rebirth.Value)
	profile.Data.LevelLimit = 100 * 2 ^ player.leaderstats.Rebirth.Value 
	profile.Data.Damage *= 2

	profile.Data.Level = 1
	player.leaderstats.Level.Value = profile.Data.Level

	profile.Data.Gold = 0
	player.leaderstats.Gold.Value = profile.Data.Gold

	player.Stats.GoldBoost.Value = profile.Data.GoldBoost
	player.Stats.XPBoost.Value = profile.Data.XPBoost
	player.Stats.DamageBoost.Value = profile.Data.DamageBoost
	player.Stats.RewardsBoost.Value = profile.Data.RewardsBoost
	player.Stats.LevelLimit.Value = profile.Data.LevelLimit
	player.Stats.Damage.Value = profile.Data.Damage
	
	else
		return false
	end

end

function module:AddUpgrade(player)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    if not profile then return end

	local BaseGoldMultiplier = 10

	if profile.Data.Gold >= ((100 + BaseGoldMultiplier * player.leaderstats.Rebirth.Value) * 2 ^ player.Stats.UpgradesDone.Value) then

		local function UpgradeSTATS()

			local StatsBoostsToGive = 2.5
			local BoostsToGive = 1
			local RebirthStatMultipler = 0.5

			if player.Stats.UpgradesDone.Value >= 1 then
	        profile.Data.Gold -= ((100 + BaseGoldMultiplier * player.leaderstats.Rebirth.Value) * 2 ^ player.Stats.UpgradesDone.Value)
			elseif player.Stats.UpgradesDone.Value <= 0 then
				profile.Data.Gold -= 100 + (BaseGoldMultiplier * player.leaderstats.Rebirth.Value)
	    	end

			player.leaderstats.Gold.Value = profile.Data.Gold

			profile.Data.UpgradesDone += 1
			player.Stats.UpgradesDone.Value = profile.Data.UpgradesDone

			local function AttackSpeedCalculator()
				if profile.Data.AttackSpeed + 1 <= 100 then
					profile.Data.AttackSpeed += 1
				elseif profile.Data.AttackSpeed + 1 >= 100 then
					profile.Data.AttackSpeed = 100
				end
			end

			

			if player.Stats.UpgradesDone.Value == 1 then
				BoostsToGive = 1
				
				profile.Data.GoldBoost = StatsBoostsToGive + (0.5 * player.leaderstats.Rebirth.Value)
				profile.Data.XPBoost = StatsBoostsToGive + (0.5 * player.leaderstats.Rebirth.Value)
				profile.Data.DamageBoost = StatsBoostsToGive + (0.5 * player.leaderstats.Rebirth.Value)
				profile.Data.RewardsBoost = StatsBoostsToGive + (0.5 * player.leaderstats.Rebirth.Value)
			
				AttackSpeedCalculator()
			elseif player.Stats.UpgradesDone.Value > 1 then
				BoostsToGive = 2 ^ player.Stats.UpgradesDone.Value

				profile.Data.GoldBoost = ((StatsBoostsToGive + (0.5 * player.leaderstats.Rebirth.Value)) * BoostsToGive)
				profile.Data.XPBoost = ((StatsBoostsToGive + (0.5 * player.leaderstats.Rebirth.Value)) * BoostsToGive)
				profile.Data.DamageBoost = ((StatsBoostsToGive + (0.5 * player.leaderstats.Rebirth.Value)) * BoostsToGive)
				profile.Data.RewardsBoost = ((StatsBoostsToGive + (0.5 * player.leaderstats.Rebirth.Value)) * BoostsToGive)

				AttackSpeedCalculator()
			end

		end

		UpgradeSTATS()

		player.Stats.GoldBoost.Value = profile.Data.GoldBoost
		player.Stats.XPBoost.Value = profile.Data.XPBoost
		player.Stats.DamageBoost.Value = profile.Data.DamageBoost
		player.Stats.RewardsBoost.Value = profile.Data.RewardsBoost
		player.Stats.AttackSpeed.Value = profile.Data.AttackSpeed

	else
		print("Not Enough Gold: " , ((100 + BaseGoldMultiplier * player.leaderstats.Rebirth.Value) * 2 ^ player.Stats.UpgradesDone.Value) )
	end

end

--- LeaderStats STUFF


--- EXP STUFF

function module:AddXP(player, amount)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    if not profile then return end

	if player.leaderstats.Level.Value < player.Stats.LevelLimit.Value then

    profile.Data.XP += (amount * profile.Data.XPBoost) * EXPBOOST.Value
    player.Stats.XP.Value = profile.Data.XP

	else
		return false
	end
end

function module:CheckXP(player)
    local Profiles = module.Profiles
    local profile = Profiles[player]

	if player.Stats.XP.Value >= player.Stats.XPNeeded.Value then
		profile.Data.XP = 0
		profile.Data.Level += 1
	
		player.Stats.XP.Value = profile.Data.XP
		player.leaderstats.Level.Value = profile.Data.Level
	else
		return false
	end
	
	profile.Data.XPNeeded = (50 * 2 ^ player.leaderstats.Level.Value)
	player.Stats.XPNeeded.Value = profile.Data.XPNeeded

end

--- EXP STUFF


--- STATS STUFF

function module:AddTotalGoldEarned(player, amount)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    if not profile then return end

    profile.Data.TotalGoldEarned += (amount * profile.Data.GoldBoost) * GOLDBOOST.Value
    player.Stats.TotalGoldEarned.Value = profile.Data.TotalGoldEarned
end

function module:AddTotalBlocksMined(player, amount)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    if not profile then return end

    profile.Data.TotalBlocksMined += amount
    player.Stats.TotalBlocksMined.Value = profile.Data.TotalBlocksMined
end

--- STATS STUFF


--- Equipment STUFF

function module:EquipPickaxe(player, itemName)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    if not profile then return end

    profile.Data.PickaxeEquipped = itemName
    player.Equipped.PickaxeEquipped.Value = profile.Data.PickaxeEquipped
end

--- Equipment STUFF


--- Functions? which i don't use...

function module:Get(player, key)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    assert(profile.Data[key], string.format("Data Does not Exist for %s", key))

    return profile.Data[key]
end

function module:Set(player, key, value)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    assert(profile.Data[key], string.format("Data Does not Exist for %s", key))
    
    assert(type(profile.Data[key]) == type(value))

    profile.Data[key] = value
end

function module:Update(player, key, callback)
    local Profiles = module.Profiles
    local profile = Profiles[player]
    
    local oldData = self:Get(player, key)
    local newData = callback(oldData)

    self:Set(player, key, newData)
end

--- Functions? which i don't use...


---

return module

You make Functions in the Manager then use it with require in scripts like:

local ServerScriptService = game:GetService("ServerScriptService")
local playerdatahandler = require(script.Parent.Manager)

then you can use it like:

playerdatahandler:FunctionName(key1, key2, etc.)
Data:
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")

local Template = require(script.Parent.Template)
local ProfileService = require(ServerScriptService.Libs.ProfileService)
local Manager = require(script.Parent.Manager)

-- Always set to Production when publishing
local ProfileStore = ProfileService.GetProfileStore("Production", Template)

local function GiveLeaderstats(player: Player)

	local profile = Manager.Profiles[player]
	if not profile then return end
	
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"
	
	local Gold = Instance.new("NumberValue", leaderstats)
	Gold.Name = "Gold"
	Gold.Value = profile.Data.Gold
	
	local Level = Instance.new("NumberValue", leaderstats)
	Level.Name = "Level"
	Level.Value = profile.Data.Level
	
	local Rebirth = Instance.new("NumberValue", leaderstats)
	Rebirth.Name = "Rebirth"
	Rebirth.Value = profile.Data.Rebirth

end

local function GiveOtherStuff(player: Player)

	local profile = Manager.Profiles[player]
	if not profile then return end
	
	local Stats = Instance.new("Folder", player)
	Stats.Name = "Stats"
	
	local Equipped = Instance.new("Folder", player)
	Equipped.Name = "Equipped"

	local Gifts = Instance.new("Folder", player)
	Gifts.Name = "Gifts"
	--- Folders
	
	local XP = Instance.new("NumberValue", Stats)
	XP.Name = "XP"
	XP.Value = profile.Data.XP

	local XPNeeded = Instance.new("NumberValue", Stats)
	XPNeeded.Name = "XPNeeded"
	XPNeeded.Value = profile.Data.XPNeeded

	local LevelLimit = Instance.new("NumberValue", Stats)
	LevelLimit.Name = "LevelLimit"
	LevelLimit.Value = profile.Data.LevelLimit

	local AttackSpeed = Instance.new("NumberValue", Stats)
	AttackSpeed.Name = "AttackSpeed"
	AttackSpeed.Value = profile.Data.AttackSpeed

	local Damage = Instance.new("NumberValue", Stats)
	Damage.Name = "Damage"
	Damage.Value = profile.Data.Damage

	local DamageBoost = Instance.new("NumberValue", Stats)
	DamageBoost.Name = "DamageBoost"
	DamageBoost.Value = profile.Data.DamageBoost
	
	local RewardsBoost = Instance.new("NumberValue", Stats)
	RewardsBoost.Name = "RewardsBoost"
	RewardsBoost.Value = profile.Data.RewardsBoost

	local UpgradesDone = Instance.new("NumberValue", Stats)
	UpgradesDone.Name = "UpgradesDone"
	UpgradesDone.Value = profile.Data.UpgradesDone

	local XPBoost = Instance.new("NumberValue", Stats)
	XPBoost.Name = "XPBoost"
	XPBoost.Value = profile.Data.XPBoost

	local GoldBoost = Instance.new("NumberValue", Stats)
	GoldBoost.Name = "GoldBoost"
	GoldBoost.Value = profile.Data.GoldBoost
	
	local TotalGoldEarned = Instance.new("NumberValue", Stats)
	TotalGoldEarned.Name = "TotalGoldEarned"
	TotalGoldEarned.Value = profile.Data.TotalGoldEarned
	
	local TotalBlocksMined = Instance.new("NumberValue", Stats)
	TotalBlocksMined.Name = "TotalBlocksMined"
	TotalBlocksMined.Value = profile.Data.TotalBlocksMined

	local PickaxeEquipped = Instance.new("StringValue", Equipped)
	PickaxeEquipped.Name = "PickaxeEquipped"
	PickaxeEquipped.Value = profile.Data.PickaxeEquipped

	local GiftGold = Instance.new("NumberValue", Gifts)
	GiftGold.Name = "GiftGold"
	GiftGold.Value = profile.Data.GiftGold

	local GiftAttackSpeed = Instance.new("NumberValue", Gifts)
	GiftAttackSpeed.Name = "GiftAttackSpeed"
	GiftAttackSpeed.Value = profile.Data.GiftAttackSpeed

	local GiftDamageBoost = Instance.new("NumberValue", Gifts)
	GiftDamageBoost.Name = "GiftDamageBoost"
	GiftDamageBoost.Value = profile.Data.GiftDamageBoost

	local GiftRewardsBoost = Instance.new("NumberValue", Gifts)
	GiftRewardsBoost.Name = "GiftRewardsBoost"
	GiftRewardsBoost.Value = profile.Data.GiftRewardsBoost

	local GiftXPBoost = Instance.new("NumberValue", Gifts)
	GiftXPBoost.Name = "GiftXPBoost"
	GiftXPBoost.Value = profile.Data.GiftXPBoost

	local GiftGoldBoost = Instance.new("NumberValue", Gifts)
	GiftGoldBoost.Name = "GiftGoldBoost"
	GiftGoldBoost.Value = profile.Data.GiftGoldBoost
	
end


local function PlayerAdded(player: Player)
	local profile = ProfileStore:LoadProfileAsync("Player_"..player.UserId)
	if profile == nil then
		player:Kick("Data issue, try again shortly. If issue persists, contact us!")
		return
	end
	
	profile:AddUserId(player.UserId)
	profile:Reconcile()
	profile:ListenToRelease(function()
		Manager.Profiles[player] = nil
		player:Kick("Data issue, try again shortly. If issue persists, contact us!")
	end)
	
	if player:IsDescendantOf(Players) == true then
		Manager.Profiles[player] = profile
		GiveLeaderstats(player)
		GiveOtherStuff(player)
	else
		profile:Release()
	end
end

for _, player in ipairs(Players:GetPlayers()) do
	task.spawn(PlayerAdded, player)
end

Players.PlayerAdded:Connect(PlayerAdded)

Players.PlayerRemoving:Connect(function(player: Player)
	local profile = Manager.Profiles[player]
	if not profile then return end
	profile:Release()
end)

For the data as you can see, you first give their paths
image

Then DataStore Name, in here which is “Production”
image

Then you can add Functions to make things easier:

Then PlayerAdded Stuff:

Don’t forget to call functions:
image

With this, you are ready to use ProfileService!

For Inventory Function:

To Template you add Inventroy as
Inventory = {}
then you can use it however you want

-- Add an item to the player's inventory
function module:AddToInventory(player, itemName, amount)
    local profile = module.Profiles[player]
    if not profile then return end

    -- Check if the item is already in the inventory, if not, create it
    if not profile.Inventory[itemName] then
        profile.Inventory[itemName] = 0
    end

    -- Add the specified amount to the inventory
    profile.Inventory[itemName] = profile.Inventory[itemName] + amount
end

-- Use this function to retrieve the player's inventory
function module:GetInventory(player)
    local profile = module.Profiles[player]
    if not profile then return end

    return profile.Inventory
end
1 Like