How To Save a Folder to DataStoreService

How would I add an object to the datastore service? That’s all my issue is.

Unfortunately, saving userdata to a datastore is not possible. What exactly is inside the folder that you need to save?

This topic seems to have some pretty good responses related to this topic. Reading through it might help.

You could loop through everything in the folder.

local function saveData(plr)
      local folder = --define
      local tabletosave = {}

      for i, v in pairs(folder:GetChildren()) do
            table.insert(tabletosave, v.Name)
      end
      
      datastore:SetAsync(tabletosave, plr.UserId)
      end

game.Players.PlayerRemoving:Connect(saveData)
1 Like

There is one folder inside the folder, which contains a bunch of boolean values (11 of them). Inside the main folder there is also an intvalue and an objectvalue. That’s why I would like to save the entire folder.

Here is just an example. Then when they join you can loop through the table and make a new Instance for each value in the table.

local function saveData(plr)
      local folder = --define
      local tabletosave = {}

      for i, v in pairs(folder:GetChildrenDescendants()) do
              if v:IsA("BoolValue") then
                   local insertMe = {v.Name, v.Value, "BoolValue"}
                   table.insert(tabletosave, insertMe)
             elseif v:IsA("ObjectValue" then
                   local insertMe = {v.Name, v.Value, "ObjectValue"}
                   table.insert(tabletosave, insertMe)
            elseif v:IsA("IntValue") then
                   local insertMe = {v.Name, v.Value, "IntValue"}
                   table.insert(tabletosave, insertMe)
               end
      end
      print(tabletosave)
      local success, errormessage = function()
             datastore:SetAsync(tabletosave, plr.UserId)
      end)
end

game.Players.PlayerRemoving:Connect(saveData)
1 Like

Sorry, I don’t really know how to use datastores. How would I get back the tables and use them for the values?

Also how would I see if a value is empty and create a new one for new players?

This should get you covered:

1 Like

create a tree structure where a folder represents a table. from there i suppose you can use serialization for parts

Thanks guys. I will check out @Moonvane’s link.

1 Like

Quick questions: Would the script below work? If so, would someone be willing to rewrite it with pcalls? Thanks for all the help everyone!


local PlrCash = DSS:GetDataStore("Cash")

local PlrWeapon = DSS:GetDataStore("Weapon")

local OData = DSS:GetDataStore("OData")

local TData = DSS:GetDataStore("TData")

local TTData = DSS:GetDataStore("TTData")

local FData = DSS:GetDataStore("FData")

local FFData = DSS:GetDataStore("FFData")

local SData = DSS:GetDataStore("SData")

local SSData = DSS:GetDataStore("SSData")

local EData = DSS:GetDataStore("EData")

local NData = DSS:GetDataStore("NData")

local TEData = DSS:GetDataStore("TEData")

game.Players.PlayerAdded:Connect(function(plr)
	local stats = Instance.new("Folder")
	stats.Name = "Stats"
	stats.Parent = plr
	local weapon = Instance.new("ObjectValue")
	weapon.Name = "Weapon"
	weapon.Parent = stats
	weapon.Value = PlrWeapon:GetAsync(plr.UserId) or nil
	local cash = Instance.new("IntValue")
	cash.Name = "Cash"
	cash.Parent = stats
	cash.Value = PlrCash:GetAsync(plr.UserId) or 0
	local WeaponSSS = Instance.new("Folder")
	WeaponSSS.Parent = stats
	WeaponSSS.Name = "WeaponSSS"
	local O = Instance.new("BoolValue")
	O.Name = "O"
	O.Parent = WeaponSSS
	O.Value = OData:GetAsync(plr.UserId) or false
	local T = Instance.new("BoolValue")
	T.Name = "T"
	T.Parent = WeaponSSS
	T.Value = TData:GetAsync(plr.UserId) or false
	local TT = Instance.new("BoolValue")
	TT.Name = "TT"
	TT.Parent = WeaponSSS
	TT.Value = TTData:GetAsync(plr.UserId) or false
	local F = Instance.new("BoolValue")
	F.Name = "F"
	F.Parent = WeaponSSS
	F.Value = FData:GetAsync(plr.UserId) or false
	local FF = Instance.new("BoolValue")
	FF.Name = "FF"
	FF.Parent = WeaponSSS
	F.Value = FFData:GetAsync(plr.UserId) or false
	local S = Instance.new("BoolValue")
	S.Name = "S"
	S.Parent = WeaponSSS
	S.Value = SData:GetAsync(plr.UserId) or false
	local SS = Instance.new("BoolValue")
	SS.Name = "SS"
	SS.Parent = WeaponSSS
	SS.Value = SSData:GetAsync(plr.UserId) or false
	local E = Instance.new("BoolValue")
	E.Name = "E"
	E.Parent = WeaponSSS
	E.Value = EData:GetAsync(plr.UserId) or false
	local N = Instance.new("BoolValue")
	N.Name = "N"
	N.Parent = WeaponSSS
	N.Value = NData:GetAsync(plr.UserId) or false
	local TE = Instance.new("BoolValue")
	TE.Name = "TE"
	TE.Parent = WeaponSSS
	TE.Value = TEData:GetAsync(plr.UserId) or false
end)

game.Players.PlayerRemoving:connect(function(Player)
	PlrCash:SetAsync(Player.userId, Player.Stats.Cash.Value)
	PlrWeapon:SetAsync(Player.userId, Player.Stats.Weapon.Value)
	OData:SetAsync(Player.UserId, Player.Stats.WeaponSS.O)
	TData:SetAsync(Player.UserId, Player.Stats.WeaponSS.T)
	TTData:SetAsync(Player.UserId, Player.Stats.WeaponSS.TT)
	FData:SetAsync(Player.UserId, Player.Stats.WeaponSS.F)
	FFData:SetAsync(Player.UserId, Player.Stats.WeaponSS.FF)
	SData:SetAsync(Player.UserId, Player.Stats.WeaponSS.S)
	SSData:SetAsync(Player.UserId, Player.Stats.WeaponSS.SS)
	EData:SetAsync(Player.UserId, Player.Stats.WeaponSS.E)
	NData:SetAsync(Player.UserId, Player.Stats.WeaponSS.N)
	TEData:SetAsync(Player.UserId, Player.Stats.WeaponSS.TE)
end)```

Oh my :flushed: You should use one DataStore (You only need one)

Just use this function when saving data:

function ToSchema(Folder)
    local Schema = {};

    for _, Data in pairs(Folder:GetChildren()) do
        if next(Data:GetChildren()) and Data:IsA("Folder") then --// If the given folder has more than 1 object, save it as an Array
            Schema[Data.Name] = ToSchema(Folder)
        elseif Data:IsA("ValueBase") then --// If the object has a Value, save it to the array as its value
            Schema[Data.Name] = Data.Value
        else --// If the object is just an object, save its name as a string
            table.insert(Schema, Data.Name);
        end
    end

    return Schema
end

DataStore:UpdateAsync(Key, function()
    return ToSchema(Folder)
end)

Thanks, but that’s not what I need help with. Could you please just rewrite it with pcalls. Thanks!

I know exactly what you are trying to do, I have a script that can save parts very quickly. the issue is its over 2k lines so even using stuff like pastebin makes it hard to share. Ill try and see if I still have the script I used to auto repeat lines of code configured for this and if so ill provide it.

I basically just take the part type and then check for every property in the game.
When I save it looks a bit like:
PartType:Property1:Property2

Then all I have to do to recreate the parts is do:
Instance.new(PartType)
and then a bunch of pcalls to set properties.

It works out faster to do this way than to have a pcall or function for each part type as there are more part types than properties.

Lucky you, its still configured for both saving and loading.
All you have to do is put this in a script or local script and run, Then copy the entire output into a function, it will need a little setting up but its faster than writing it all out. (Run repeatwrite and repeatwrite2 on different runs to prevent it getting muddled up)

there’s a few bits missing so you still have to read and understand the code in order to make it work. On top of that you will need to create a function called ‘GetOriginalValue()’ that finds out if a value should be vector3, color3 or whatever else and turns it into that correct value. All I’ve done is save you writing the same thing over 200 times, you will still have to make it work.

-- Minimic2002's RepeatingScriptingHelper

List = {
	"Adornee",
	"AlwaysOnTop",
	"Anchored",
	"AnchorPoint",
	"Angle",
	"AngularActuatorType",
	"AngularLimitsEnabled",
	"AngularVelocity",
	"AnimationId",
	"ApplyAtCenterOfMass",
	"Archivable",
	"Attachment0",
	"Attachment1",
	"AttachmentFoward",
	"AttachmentPos",
	"AttachmentUp",
	"Orientation",
	"PlayOnRemove",
	"Force",
	"InFocusRadius",
	"LayoutOrder",
	"HeadColor",
	"HeadColor3",
	"AutoAssignable",
	"AutoButtonColor",
	"AutoJumpEnabled",
	"AutoLocalize",
	"AutoRotate",
	"Axes",
	"BackgroundColor3",
	"BackgroundTransparency",
	"BaseTextureId",
	"BehaviourType",
	"BlastPressure",
	"BlastRadius",
	"BodyPart",
	"BorderColor3",
	"BorderMode",
	"BorderSizePixel",
	"BottomImage",
	"BreakJointsOnDeath",
	"BrickColor",
	"Brightness",
	"CameraOffset",
	"CanBeDropped",
	"CanCollide",
	"CanvasPosition",
	"CanvasSize",
	"CartoonFactor",
	"CastShadow",
	"CelestialBodiesShown",
	"ClearTextOnFocus",
	"ClipsDescendants",
	"Coils",
	"Color3",
	"CoilsCollisionFidelity",
	"Color",
	"Contrast",
	"ConversationDistance",
	"CurrentAngle",
	"CursorPosition",
	"CurveSize0",
	"CurveSize1",
	"D",
	"Damping",
	"DesiredAngle",
	"DestoryJointRadiusPercent",
	"Disabled",
	"DisplayDistanceType",
	"DisplayName",
	"ElasticBehavior",
	"DisplayOrder",
	"EmitterSize",
	"Enabled",
	"ExplosionType",
	"ExtentsOffset",
	"ExtentsOffsetWorldSpace",
	"Face",
	"FaceCamera",
	"Faces",
	"FarIntensity",
	"FocusDistance",
	"Font",
	"FocusDistance",
	"FreeLength",
	"GoodbyeChoiceActive",
	"GoodbyeDialog",
	"Graphic",
	"GripFoward",
	"GripPos",
	"GripRight",
	"GripUp",
	"HeadsUpDisplay",
	"HealthDisplayDistance",
	"HealthDisplayType",
	"Heat",
	"Height",
	"HorizontalScrollBarInset",
	"HoverImage",
	"IgnoreGuiInset",
	"Image",
	"ImageColor3",
	"ImagePressed",
	"ImageRectOffset",
	"ImageTransparency",
	"InclinationAngle",
	"InitialPrompt",
	"Intensity",
	"InUse",
	"InverseSquareLaw",
	"JumpPower",
	"LeftArmColor",
	"LeftArmColor3",
	"Length",
	"LeftLegColor",
	"LeftLegColor3",
	"LightEmission",
	"LightInfluence",
	"LineHeight",
	"LineThickness",
	"Locked",
	"Looped",
	"Magnitude",
	"ManualActiavationOnly",
	"Massless",
	"Material",
	"MaxActivationDistance",
	"MaxAngularVelocity",
	"MaxDistance",
	"MaxForce",
	"MaxFrictionTorque",
	"MaxSpeed",
	"MaxThrust",
	"MaxVelocity",
	"MeshId",
	"MeshType",
	"MidImage",
	"MaxTorque",
	"Modal",
	"MoonAngularSize",
	"MoonTextureId",
	"Name",
	"NameDisplayDistance",
	"NameOcclusion",
	"MultiLine",
	"NearIntensity",
	"NextSelectionDown",
	"NextSelectionLeft",
	"NextSelectionRight",
	"NextSelectionUp",
	"OffsetStudsU",
	"OffsetStudsV",
	"Opacity",
	"OveralyTextureId",
	"P",
	"PantsTemplate",
	"Parent",
	"Part0",
	"Part1",
	"PixelsPerStud",
	"PlaceholderColor3",
	"PlaceholderText",
	"PlaybackSpeed",
	"PlatformStand",
	"PlayerToHideFrom",
	"Playing",
	"Position",
	"PrimaryAxisOnly",
	"Purpose",
	"Radius",
	"ReactionForceEnabled",
	"ReactionTorqueEnabled",
	"Range",
	"Reflectance",
	"RenderFidelity",
	"RequiresHandle",
	"RelativeTo",
	"ResetOnSpawn",
	"ResponseDialog",
	"Responsiveness",
	"Restitution",
	"RightArmColor",
	"RightLegColor3",
	"RigidityEnabled",
	"RightArmColor3",
	"RightLegColor",
	"RigType",
	"RiseVelocity",
	"RollOffMode",
	"RotationAxisVisible",
	"Saturation",
	"Scale",
	"ScaleType",
	"ScrollBarImageColor3",
	"ScrollBarImageTransparency",
	"ScrollBarThickness",
	"ScrollingDirection",
	"ScrollingEnabled",
	"SecondaryColor",
	"Segments",
	"Selectable",
	"Selected",
	"SelectionImageObject",
	"Shadows",
	"ShirtTemplate",
	"ShowNativeInput",
	"Sit",
	"Size",
	"SizeConstraint",
	"SizeRelativeOffset",
	"SizingMode",
	"SizeOffset",
	"SkyboxBk",
	"SkyboxDn",
	"SkyboxFt",
	"SkyboxLf",
	"SkyboxRt",
	"SkyboxUp",
	"SlectionStart",
	"SliceScale",
	"SoundGroup",
	"SoundId",
	"SparkleColor",
	"Spread",
	"StarCount",
	"Steer",
	"SteerFloat",
	"Stiffness",
	"StudsPerTileU",
	"StudsPerTileV",
	"Style",
	"SunAngularSize",
	"SurfaceColor3",
	"SurfaceTransparency",
	"Target",
	"TargetOffset",
	"TargetPoint",
	"TargetRadius",
	"TargetSurface",
	"TeamColor",
	"Text",
	"TextColor3",
	"TextEditable",
	"TextScaled",
	"TextSize",
	"TextStrokeColor3",
	"TextStrokeTransparency",
	"TextTransparency",
	"TextTruncate",
	"Texture",
	"TextureID",
	"TextureLength",
	"TextureMode",
	"TextureSpeed",
	"TextWrapped",
	"TextXAlignment",
	"TextYAlignment",
	"Thickness",
	"Threshold",
	"Throttle",
	"ThrottleFloat",
	"ThrustD",
	"ThrustP",
	"TimePosition",
	"TintColor",
	"TimePosition",
	"Tone",
	"ToolPunchThroughDistance",
	"ToolTip",
	"TopImage",
	"TorsoColor",
	"TorsoColor3",
	"Transparency",
	"TriggerDistance",
	"TriggerOffset",
	"TurnD",
	"TurnP",
	"TurnSpeed",
	"UseJumpPower",
	"UserDialog",
	"Value",
	"Velocity",
	"VertexColor",
	"Visible",
	"VerticalScrollBarInset",
	"VerticalScrollBarPosition",
	"Width0",
	"Width1",
	"Volume",
	"ZIndex",
	"ZIndexBehavior",
	"ZOffset",
}


function ReplaceRepeat(List)
	for i = 1,#List do
		local Replace = List[i]
		local TTR1 = "success, response = pcall(function()"
		local TTR2 = "	if P." .. Replace .." == nil then"
		local TTR3 = "	else"
		local TTR4 = ""
		local TTR5 = "  end"
		local TTR6 = "end)"
		local TTR7 = "if success then"
		local TTR8 = "  Text = ".."'"..Replace.."'" .. "..';' ..tostring(P.".. Replace..")"
		local TTR9 = "  table.insert(Properties,Text)"
		local TTR10 = "  success = nil"
		local TTR11 = "end"
		print(TTR1)
		print(TTR2)
		print(TTR3)
		print(TTR4)
		print(TTR5)
		print(TTR6)
		print(TTR7)
		print(TTR8)
		print(TTR9)
		print(TTR10)
		print(TTR11)
		print("")
		wait(0.1)
	end
end

function ReplaceRepeat2(List)
	for i = 1,#List do
		local Replace = List[i]
		local TTR1 = "success, response = pcall(function()"
		local TTR2 = "	if Split[1] == '".. Replace .."' then"
		local TTR0 = "  NewP.".. Replace .." = GetOriginalValue(Split,NewP.".. Replace .. ")"
		local TTR3 = "	else"
		local TTR4 =     "Error = Error .. 'ErrorMaker'"
		local TTR5 = "  end"
		local TTR6 = "end)"
		local TTR7 = "if success then"
		local TTR8 = ""
		local TTR8 = "  NewP.".. Replace .." = GetOriginalValue(Split,NewP.".. Replace .. ")"
		local TTR9 = ""
		local TTR10 = "  success = nil"
		local TTR11 = "end"
		print(TTR1)
		print(TTR2)
		print(TTR0)
		print(TTR3)
		print(TTR4)
		print(TTR5)
		print(TTR6)
		print(TTR7)
		print(TTR8)
		print(TTR9)
		print(TTR10)
		print(TTR11)
		print("")
		wait(0.1)
	end
end
wait(5)
ReplaceRepeat2(List)

Sorry, I figured out what I need to do so I will just close this post. I will open a new one soon for a pcalls rewrite. Thanks everyone!