What is a better way to save and load large amounts of parts with datastores?

Hello developers!

I recently ran into an issue with my code that I need help with. I wrote a script to save and load a players base for my game, the datastore saves by taking each of the children inside the player’s folder inside workspace (the folder contains each part of the players base) and saving it in a array. When it loads, it goes one by one through the array, checking if the name of the part contains “GRASS”, if so, then it creates the part with instances and sets its parent to the players folder. Just by reading what I said, some experienced developer out there reading this might be facepalming right now. One issue with this is when the player joins and leaves before the base can even load, all the progress is gone because the array is going to have player data, but its also going to be empty. I know that there is a way better way to what I’m doing. Like most newbie scripters, not the biggest knowledge on datastores. Not asking for anyone to write a script for me, but a guided explanation to solve my issue. Thank you.

Code –

-- Parent is ServerScriptService
local newplayer = ""
local distance = 0
local base = {}

local DataStoreService = game:GetService("DataStoreService")

local playerData = DataStoreService:GetDataStore("tybtojjbgbtgb")





local function onPlayerJoin(player)  -- Runs when players join

	-- Creates a folder for the base
	newplayer = player.Name
	local folder = Instance.new("Folder")
	folder.Name = player.Name.. "'s Base"
	folder.Parent = workspace


	local playerUserId = "Player_" .. player.UserId  --Gets player ID

	local data = playerData:GetAsync(playerUserId)  --Checks if player has stored data

	if data then

		-- Data exists for this player

		base = data

	else

		-- Data store is working, but no current data for this player

		base = {
			GRASS1 = {0,0,0},
			GRASS2 = {0,0,8},
			GRASS3 = {0,0,-8},
			GRASS4 = {8,0,0},
			GRASS5 = {-8,0,0},
			GRASS6 = {8,0,8},
			GRASS7 = {8,0,-8},
			GRASS8 = {-8,0,-8},
			GRASS9 = {-8,0,8}
		}

	end
	

	repeat wait() until player.Character
	wait()
	-- Loads in last saved base when player joins


	--creation
	
	local basepart = Instance.new("Part")
	local basepartdesign = Instance.new("Decal")
	
	basepartdesign.Face = Enum.NormalId.Top
	basepartdesign.Texture = "http://www.roblox.com/asset/?id=9475664047"
	basepartdesign.Transparency = 0.5
	basepartdesign.Parent = basepart
	
	basepart.Size = Vector3.new(800,0.1,800)
	basepart.Anchored = true
	basepart.Position = player.RespawnLocation.Position
	basepart.Transparency = 1
	basepart.CanCollide = false
	basepart.Name = "BASEPART"
	basepart.Parent = workspace:WaitForChild(newplayer.. "'s Base")
	
	for key, value in pairs(base) do
		local create = Instance.new("Part")
		local decoration = Instance.new("Decal")
		local clicked = Instance.new("ClickDetector")
		local effect = workspace.BaseFunctions.EditLand:Clone()
		
		decoration.Face = Enum.NormalId.Top
		decoration.Texture = "http://www.roblox.com/asset/?id=19886465"
		decoration.Transparency = 0.5
		decoration.Name = "design"
		decoration.Parent = create
		
		clicked.CursorIcon = "http://www.roblox.com/asset/?id=9423559062"
		clicked.MaxActivationDistance = 50
		clicked.Parent = create
		
		effect.Disabled = false
		effect.Parent = clicked

		if key:match("GRASS") then -- Checks for grass type
		create.Material = Enum.Material.Grass
		create.Size = Vector3.new(8,1,8)
		create.BrickColor = BrickColor.new("Parsley green")
		create.Anchored = true
		create.Position = Vector3.new(table.unpack(value))
		create.Position = Vector3.new(create.Position.X+player.RespawnLocation.Position.X,create.Position.Y,create.Position.Z)
		create.Name = key
		create.Parent = workspace:WaitForChild(newplayer.. "'s Base")
		end
	end
end

local function onPlayerExit(player)  --Runs when players exit

local success, err = pcall(function()

		local playerUserId = "Player_" .. player.UserId
		local children = workspace[player.Name.. "'s Base"]:GetChildren()
		local savebase = {}
		for i = 1, #children do
			savebase[children[i].Name] = {children[i].position.X-player.RespawnLocation.Position.X, 0, children[i].position.Z}
		end
		

		playerData:SetAsync(playerUserId, savebase) --Saves player data

	end)



	if not success then

		warn('Could not save data!')

	end
	workspace:WaitForChild(player.Name.. "'s Base"):Destroy()
end



game.Players.PlayerAdded:Connect(onPlayerJoin)

game.Players.PlayerRemoving:Connect(onPlayerExit)


3 Likes