Saving and loading a models color in datastores

function savePlace(player)
	local models = {}
	save:InvokeClient(player, 'Saving')
	for _, model in pairs(bases:FindFirstChild(player.Name).ItemHolder:GetChildren()) do
		local modelData = {}		
		local primaryPart = model.PrimaryPart
		local position = bases:FindFirstChild(player.Name).PrimaryPart.CFrame:inverse() * 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
	end
	modelDataStore:SetAsync(player.UserId, models)
	permanentSave(player)
	_G.playerData[player.UserId] = nil
	save:InvokeClient(player, 'Save Complete!')
end

function loadPlace(player)
	local playersBase = bases:FindFirstChild('EmptyBase')
	playersBase.Name = player.Name
	playersBase.OwnerGui.Owner.Text = player.Name
	playersBase.ItemHolder:ClearAllChildren()
	
	local models = modelDataStore:GetAsync(player.UserId)
	for _, modelData in pairs(models) do
		local targetModel = modelData.ModelName
		local information = modelData.Position
		local newModel = items:FindFirstChild(targetModel):Clone()
		local position = bases:FindFirstChild(player.Name).PrimaryPart.CFrame * 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
end

These are my save and load functions for my placement system. I’ve been currently working on how to save a models coloring though, and have run into some problems. For 1 - I don’t believe you can save Colors in a datastore? and 2 - I wouldn’t have the slightest clue on how to save each color of the models part properly. Obviously if it’s just one part in the model it wouldn’t matter, but if the model has say 10 parts in it then it would become hazardous.

Continuing on, and adding some more, probably vital information. Each model has a part called ‘Primary’ and ‘Secondary’ (for example, a tree, all the leaves parts would be called ‘Primary’ and the trunk would be called ‘Secondary’) this is because I have a coloring system that allows models to get changed colors. My thought would be if I just saved 1 part called Primary color, and another part called Secondary color. That way I’m not saving every part in the models color, just the primary and secondary color, then in the load function I could just load the model, get its children. Whatever part is called Primary give it the primary color, and vice versa.

So that kinda solves the issues of having to save multiple parts colors and only needing to just save the Primary and Secondary colors, but I’m still not sure how to go about saving the colors in the first place. Any help or information would be greatly appreciated :smiley:

2 Likes

You’ll simply have to deconstruct the color into an array when saving and reconstruct the Color3 value loading:

local Color = Color3.new(1, 1, 1)
local SaveableColor3 = {Color.r, Color.g, Color.b}
local LoadedColor3 = {}
local Color = Color3.new(LoadedColor3[1], LoadedColor3[2], LoadedColor3[3])

The primary and secondary color system you have is good. It’s nice and simple, both for the user the developer.

if model:FindFirstChild('Sign') == nil then
		local primaryColor = model:FindFirstChild('Primary').BrickColor
		local secondaryColor = model:FindFirstChild('Secondary').BrickColor
		modelData.PrimaryColor = primaryColor
		modelData.SecondaryColor = secondaryColor
	end

this what I have written up quickly, forgot to mention that it saves brickcolor (although, it wouldn’t matter if I saved it as just the color of the part?) but this is the error I get:

Cannot store Array in DataStore

Weird, what’s your saving code?

Arrays should be able to be saved fine.

It’s the top function in the original post, but ill repost just the save here with the edit:

function savePlace(player)
	local models = {}
	save:InvokeClient(player, 'Saving')
	for _, model in pairs(bases:FindFirstChild(player.Name).ItemHolder:GetChildren()) do
		local modelData = {}		
		local primaryPart = model.PrimaryPart
		local position = bases:FindFirstChild(player.Name).PrimaryPart.CFrame:inverse() * primaryPart.Position
		local direction = primaryPart.CFrame.lookVector
		if model:FindFirstChild('Sign') == nil then
			local primaryColor = model:FindFirstChild('Primary').BrickColor
			local secondaryColor = model:FindFirstChild('Secondary').BrickColor
			modelData.PrimaryColor = primaryColor
			modelData.SecondaryColor = secondaryColor
		end
		modelData.ModelName = model.Name
		modelData.Position = {position.X, position.Y, position.Z, direction.X, direction.Y, direction.Z}
		models[#models + 1] = modelData
	end
	modelDataStore:SetAsync(player.UserId, models)
	permanentSave(player)
	_G.playerData[player.UserId] = nil
	save:InvokeClient(player, 'Save Complete!')
end

EDIT the reason theres a if model:FindFirstChild('Sign') == nil then is because there’s are models that don’t have primary and secondary parts (they cant be colored) but they have signs in them so i just use that as a way to know what parts can’t XD i know it’s dodgy

1 Like

One issue could be that it’s trying to save a ‘mixed’ table. A mixed table is a table that has both arrays (number indexes) and dictionaries (string/bool/etc. indexes). For example:

{ -- this table is an array
    [1] = {Name = "Thing 1"}; -- this table is a dictionary
    [2] = {Name = "Thing 2"}; -- this table is a dictionary
}

This case is of dictionaries inside an array. However, I’ve used arrays inside dictionaries (the opposite of what you are doing) before, so this is some weird behaviour. Most likely some limitation to do with arrays (or an un-limitation to do with dictionaries). I’m unsure if this is exactly the issue, though.

You could try making modelData an array and see if it fixes your problem. It won’t be great to use, but it’ll let you do what you want.

But I mean the way I’m doing it, could I just save the BrickColor’s name instead of the BrickColor? that way it’d be a string. Considering modelData is saving the models name (modelData.ModelName) which is a string, it should theoretically be able to save

It shouldn’t be the color table causing the issue, though. I’m talking about each modelData table. And you could do that, yeah.

To add:

Just tested and I got it to work :smiley:

1 Like

I’m sorry, I am new to working with data stores in this way, What does save:InvokeClient(player, ‘Saving’) do?