Data Save For A Placement System

Hello,
Okay, so, I have this script here that saves instances created by the player. It was working fine until, I had the idea to save multipl datas. And it broke.

  • The plot variable is just nothing, it works fine.
  • The plot prints correctly,
    image
    no worries about it too, but, the problem is that the system doesn’t work, even thought there’s no errors in the output.

My script:

-- 1. Data Save
-- 1.1 Get Plot

local players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
local plotHandler = require(script.Parent.Parent.ServerModules.PlotHandler)
local remoteRF = replicatedStorage.Events.requestPlot
local dataStoreService = game:GetService("DataStoreService")

local dataStore1 = dataStoreService:GetDataStore("SaveObjectsInSave1")
local dataStore2 = dataStoreService:GetDataStore("SaveObjectsInSave2")
local dataStore3 = dataStoreService:GetDataStore("SaveObjectsInSave3")
local dataStore4 = dataStoreService:GetDataStore("SaveObjectsInSave4")
local dataStore5 = dataStoreService:GetDataStore("SaveObjectsInSave5")
local dataStore6 = dataStoreService:GetDataStore("SaveObjectsInSave6")

local tries = 3
local dataloaded = nil

local function assignRandomPlot(plr)
	plotHandler.assignRandomPlot(workspace.Plots, plr)
end

local function assignPlot1(plr)
	plotHandler.assignPlot1(workspace.Plots, plr)
end
local function assignPlot3(plr)
	plotHandler.assignPlot3(workspace.Plots, plr)
end
local function assignPlot2(plr)
	plotHandler.assignPlot2(workspace.Plots, plr)
end
local function assignPlot4(plr)
	plotHandler.assignPlot4(workspace.Plots, plr)
end

local function removePlot(plr)
	plotHandler.removePlot(workspace.Plots, plr)
end

local function requestPlot(plr)
	return plotHandler.returnPlot(workspace.Plots, plr)
end

local function serialize(plr, plot, data)
	print(plot)
	if dataloaded and plot then

		if plot then
			local key = plr.UserId
			local count = 0

			local data = {}

			for i, obj in ipairs(plot:WaitForChild("placedObjects"):GetChildren()) do
				table.insert(data, {
					["name"] = obj.Name,
					["transform"] = {
						["x"] = obj.PrimaryPart.CFrame.X;
						["y"] = obj.PrimaryPart.CFrame.Y;
						["z"] = obj.PrimaryPart.CFrame.Z;
						["r"] = obj.PrimaryPart.Orientation.Y;
						["r2"] = obj.PrimaryPart.Orientation.X
					},
					["color"] = {
						["paintableR"] = obj:WaitForChild("Paintable1").Color.R;
						["paintableG"] = obj:WaitForChild("Paintable1").Color.G;
						["paintableB"] = obj:WaitForChild("Paintable1").Color.B
					}
				})
			end

			local success, err

			repeat
				success, err = pcall(function()
					data:SetAsync(key, data)
				end)

				count = count + 1
			until count >= tries or success

			if not success and not plot then
				warn("Data could not be set." .. tostring(err))

				return
			else
				game.ReplicatedStorage.Events.DataGUI:FireClient(plr)

				return
			end
		end
	end
end

local function deserialize(plr, plot, dataS)
	print(plot)
	if plot then
		local key = plr.UserId
		local count = 0

		local data

		local success, err

		repeat
			success, err = pcall(function()
				data = dataS:GetAsync(key)
			end)

			count = count + 1
		until count >= tries or success

		if not success then
			warn("Failed to read data." .. tostring(err))
			game.ReplicatedStorage.Events.DataGUI:FireClient(plr)
			wait(17)
			plr:Kick("Failed to read data. Please rejoin the game.")

			return
		end

		if data then

			for i, saved in ipairs(data) do
				local loadedModel = replicatedStorage.Objects:FindFirstChild(saved.name):Clone()

				if loadedModel then
					loadedModel:SetPrimaryPartCFrame(CFrame.new(saved.transform.x, saved.transform.y, saved.transform.z)*CFrame.Angles(0, math.rad(saved.transform.r), 0))
					loadedModel.Paintable1.BrickColor = BrickColor.new(saved.color.paintableR, saved.color.paintableG, saved.color.paintableB)
					print(plot)
					loadedModel.Parent = plot.placedObjects
				else
					return
				end
			end

			dataloaded = true
		else
			dataloaded = true
		end
	end
end

-- 1.3 Remove objects and set values to nil

local function unloadTycoonData(plr, plot)
	
	for _, obj in ipairs(plot.placedObjects:GetChildren()) do
		obj:Destroy()
	end

	plot.Owner.Value = nil
	plot.OwnerName.Value = ""
	plot.Plot.Size = Vector3.new(450,0.1,450)
	for i, parts in pairs(plot.Banbox:GetChildren()) do
		if parts:IsA("BasePart") then
			parts.Transparency = 0
			parts.CanCollide = true
		end
	end

	-- Remove banboxes

	for i, parts in pairs(plot.LargePlotBanbox:GetChildren()) do
		if parts:IsA("BasePart") then
			parts.Transparency = 1
			parts.CanCollide = false
		end
	end

	for i, parts in pairs(plot.Banbox:GetChildren()) do
		if parts:IsA("BasePart") then
			parts.Transparency = 1
			parts.CanCollide = false
		end
	end
end

game.ReplicatedStorage.Events.BuildModeEvents.ChoosePlot.OnServerEvent:Connect(function(player, argument)
	if argument == "RandomPlot" then
		assignRandomPlot(player)
	elseif argument == "Plot1" then
		assignPlot1(player)
	elseif argument == "Plot2" then
		assignPlot2(player)
	elseif argument == "Plot3" then
		assignPlot3(player)
	elseif argument == "Plot4" then
		assignPlot4(player)
	elseif argument == "RemovePlot" then
		removePlot(player)
	end
end)

game.ReplicatedStorage.Events.BuildModeEvents.LoadSaving.OnServerEvent:Connect(function(player, argument)
	local plot = plotHandler.returnPlot(workspace.Plots, player)
	if plot then
		if argument == "Save1" then
			deserialize(player, plot, dataStore1)
		elseif argument == "Save2" then
			deserialize(player, plot, dataStore2)
		elseif argument == "Save3" then
			deserialize(player, plot, dataStore3)
		elseif argument == "Save4" then
			deserialize(player, plot, dataStore4)
		elseif argument == "Save5" then
			deserialize(player, plot, dataStore5)
		elseif argument == "Save6" then
			deserialize(player, plot, dataStore6)
		end	
	end
end)

players.PlayerRemoving:Connect(function(plr)
	local plotToSave = plotHandler.returnPlot(workspace.Plots, plr)
	if plotToSave then
		unloadTycoonData(plr, plotToSave)
		serialize(plr, plotToSave, dataStore1)
		serialize(plr, plotToSave, dataStore2)
		serialize(plr, plotToSave, dataStore3)
		serialize(plr, plotToSave, dataStore4)
		serialize(plr, plotToSave, dataStore5)
		serialize(plr, plotToSave, dataStore6)
	end
end)

game:BindToClose(function()
	for i, plr in ipairs(players:GetPlayers()) do
		local plot = plotHandler.returnPlot(workspace.Plots, plr)
		if plot then
			serialize(plr, plot, dataStore1)
			serialize(plr, plot, dataStore2)
			serialize(plr, plot, dataStore3)
			serialize(plr, plot, dataStore4)
			serialize(plr, plot, dataStore5)
			serialize(plr, plot, dataStore6)
		end
	end
end)

remoteRF.OnServerInvoke = requestPlot

Any help? Thanks.

There wont be any errors as your pcalling it?

No errors, as I said.

But, in the if not success and not plot then line, if I remove not plot, it will show this error when I leave:

What value is plot?
Because if you do “not plot”, then it checks if the value is false if it is a boolean or if it doesnt exist.

It is putting that error because it is running the code inside

1 Like

Plot is an object value from a module script (if you want the script tell me), yes I know, but I want the server to check if plot is not nil.

If I were you, I would do the FireClient(plr) line at the top if it was “success” and then if it wasn’t run the code. Basically switch the 2 pieces of code around

Could you write that for me please, I didn’t really understand.

Ok no problem

if success and plot then
				game.ReplicatedStorage.Events.DataGUI:FireClient(plr)

				return
			else
				warn("Data could not be set." .. tostring(err))

				return
			end

Can you show the script for plothandler?

Thanks for the help. Gonna try this.

it just make it much easier to understand and probably more likely to work

Sure, here is it:
It’s a module script.

local plotHandler = {}

function plotHandler.assignRandomPlot(loc, plr)
	for i, plt in pairs(loc:GetChildren()) do
		if plt.Owner.Value == nil then
			plt.Owner.Value = plr
			plt.OwnerName.Value = plr.Name
			
			break
		end
	end
end

function plotHandler.assignPlot1(loc, plr)
	for i, plt in pairs(loc:GetChildren()) do
		if plt.Name == "Plot1" then
			if plt.Owner.Value == nil then
				plt.Owner.Value = plr
				plt.OwnerName.Value = plr.Name

				break
			end
		end
	end
end

function plotHandler.assignPlot2(loc, plr)
	for i, plt in pairs(loc:GetChildren()) do
		if plt.Name == "Plot2" then
			if plt.Owner.Value == nil then
				plt.Owner.Value = plr
				plt.OwnerName.Value = plr.Name

				break
			end
		end
	end
end

function plotHandler.assignPlot3(loc, plr)
	for i, plt in pairs(loc:GetChildren()) do
		if plt.Name == "Plot3" then
			if plt.Owner.Value == nil then
				plt.Owner.Value = plr
				plt.OwnerName.Value = plr.Name

				break
			end
		end
	end
end

function plotHandler.assignPlot4(loc, plr)
	for i, plt in pairs(loc:GetChildren()) do
		if plt.Name == "Plot4" then
			if plt.Owner.Value == nil then
				plt.Owner.Value = plr
				plt.OwnerName.Value = plr.Name

				break
			end
		end
	end
end

function plotHandler.returnPlot(loc, plr)
	for i, plt in pairs(loc:GetChildren()) do
		if plt.Owner.Value == plr and plt.OwnerName.Value == plr.Name then
			return plt
		end
	end
end

function plotHandler.removePlot(loc, plr)
	for i, plt in pairs(loc:GetChildren()) do
		if plt.Owner.Value == plr and plt.OwnerName.Value == plr.Name then
			plt.Owner.Value = nil
			plt.OwnerName.Value = nil
			
			break
		end
	end
end

return plotHandler

i just spotted why are you using all these different functions that do the same job, couldnt you reuse one?

This is for a multiple save system, so it can save multiple buildings. And for the plot too, to get a specific plot the player wants to get it.

okay that makes sense
(char limit)

1 Like

is the error still there?
(char limit)

1 Like

Same error.

where are you running that function?

Here:
image