Saving parts/models via datastore?

function savePlace(player)
	local modelData = {}
	for _, model in pairs(bases:FindFirstChild(player.Name).ItemHolder:GetChildren()) do
		local modelDataHolder = {}		
		local primaryPart = model.PrimaryPart
		local position = primaryPart.Position
		local direction = primaryPart.CFrame.lookVector
		modelDataHolder.ModelName = model.Name
		modelDataHolder.Position = {position.X, position.Y, position.Z, direction.X, direction.Y, direction.Z}
		modelData.ModelName = modelDataHolder.ModelName
		modelData.Position = modelDataHolder.Position
		print(modelData.ModelName)
	end
	modelDataStore:SetAsync(player.UserId, modelData)
	print('done')
end

This is what I have atm for it. It prints modelData.ModelName with a different name each time, so idk if that’s right or not :man_shrugging: It might not be but I thought since it’s a different name each time it’s gonna be saving them all

EDIT

Ok yea, i believe now it might not being saving everything properly, and only saving one model, but I don’t know how to make it save every model. I thought by adding another table, and adding all the values for each model to that table, then putting that table inside the modelData it’d work

since I suppose that modelData is supposed to keep information about individual models, what I’d do is this:
move the modelData variable inside the loop, and before the loop have a table named “models”
before moving to the next model to save, I’d add the modelData to the models
for that, you can go through two ways:
either manually set the index numerically like

models[#models+1] = modelData

or

table.insert(models, modelData) – not sure if it could work like models:insert(modelData)

that way you will have all the modelData’s in one table, sorted by numerical indexes

function savePlace(player)
	local models = {}
	for _, model in pairs(bases:FindFirstChild(player.Name).ItemHolder:GetChildren()) do
		local modelData = {}		
		local primaryPart = model.PrimaryPart
		local position = primaryPart.Position
		local direction = primaryPart.CFrame.lookVector
		modelData.ModelName = model.Name
		modelData.Position = {position.X, position.Y, position.Z, direction.X, direction.Y, direction.Z}
		models[#models + 1] = modelData
		print(models.ModelName)
	end
	modelDataStore:SetAsync(player.UserId, models)
	print('done')
end

Now the print models.ModelName just prints nil. Not sure if I did it as you said though :confused: was a little confused on what needed to be moved and what not

it does look like what I had in mind, so the data should be saved accordingly
instead, it’s what you tried to print that is different
the ‘models’ table itself won’t have a ModelName key
but, considering you have atleast one model, models[1].ModelName should
edit: ‘models’ itself is supposed to contain the modelData of each individual model, and I thought of using numerical indexes considering that a model might reoccur (and therefore it’s name)
I also didn’t think there would be issues with gaps in the numerical indexes because you rebuild the table each time you save
you don’t have to know how the indexes themselves look if you’re going to iterate through them with a for i,v in pairs loop

1 Like

function loadPlace(player)
local playersBase = bases:FindFirstChild(‘EmptyBase’)
playersBase.Name = player.Name
playersBase.ItemHolder:ClearAllChildren()

	local modelData = modelDataStore:GetAsync(player.UserId)
	local targetModel = modelData.ModelName
	local information = modelData.Position
	local newModel = items:FindFirstChild(targetModel):Clone()
	local position = Vector3.new(information[1], information[2], information[3])
	local lookVector = Vector3.new(information[4], information[5], information[6])
	newModel:SetPrimaryPartCFrame(CFrame.new(position, position + (lookVector * 5)))
	newModel.Parent = bases:FindFirstChild(player.Name).ItemHolder
end

Ok, well believe everything is saving (although when i put print models[1].ModelName it printed the same model 4 times, so idk :man_shrugging:

Now getting error in the load,

Argument 1 missing or nil

On this line

local newModel = items:FindFirstChild(targetModel):Clone()

I suppose it prints the same name 4 times because [1] refers to first entry in the table, regardless of how many are there
since you edited the way savePlace() handles data, you need to change it accordingly in loadPlace() function too
namely, when you use GetAsync() to load the data from the datastore, you’ll recieve ‘models’, and not ‘modelData’, and you’ll have to iterate through it like this

local models = modelDataStore:GetAsync(player.UserId)
for _, modelData in pairs(models) do
– use of modelData here
end

2 Likes

Works!! :smiley: THANK YOU SO MUCH!!! :smiley:

Wait… just found a new problem :cry: it saves and loads, but since there are 6 bases right, each with a different position in the world, if you come back a later day and get put in a different base and load your models, it loads them in the other bases instead of your own base… :confused:

maybe you should save their positions relative to the baseplate they are on or something like that

Each base has a Part called ‘Base’ If I made that the PrimaryPart for each base, would there be a way to save each persons base based on the base parts position and orientation?

Ideally, you shouldn’t save anything assuming a base will keep the same position in the world, as you may want to move it at any point in time. Instead, just save the relative position of the model to the base, and use that relative position to place the model again when the player gets a base in a new server.

1 Like

I haven’t got a clue as to how to do that… :confused:

If you don’t need to account for orientation, you can simply take away the tycoonBaseplate’s position when saving, and add it back on when you load. for example:

saving:

local position = primaryPart.Position - tycoonBaseplate.Position

loading:

local position = Vector3.new(information[1], information[2], information[3]) + tycoonBaseplate.Position

Back when i made restaurant tycoon, I didn’t know how to deal with the problem of orientation so I simply put all the tycoons in one long line. xD

However, since you need to account for the orientation, you need to use the CFrame of the tycoon baseplate instead of position.

saving:

local position = tycoonBaseplate.CFrame:inverse() * primaryPart.Position

loading:

local position = tycoonBaseplate.CFrame * Vector3.new(information[1], information[2], information[3])

I hope that works and i hope it makes sense!

10 Likes

For me it says: 103: Arrays is not allowed in Data Stores. What to do?

Hay, it’s probably very late, but this article should guide you through this!

6 Likes