Saving a players Accessorys plus clothing

Hello I’ve ran into a issue to where I want my characters Accessory’s to be saved by pushing a specific GUI btn and then to be loaded when pressed by another specific GUI btn. Since im fairly new to Datastores, I don’t understand how it works. I’ve tried to write my own code and I’ve received nothing, like nothing works, no errors or even prints.

local Datastore = game:GetService("DataStoreService")
local Data = Datastore:GetDataStore("DataStore")
local Players = game:GetService("Players")

local properties = {"ShirtID, PantsID, Accessorys"}
local playersData = {}

local function SerializeData(character)
	local data = {}
	local Accessory  

	for _, v in ipairs(character:GetChildren()) do
		if v:IsA("Accessory") then
			Accessory = v
		end
	end

	data["Accessorys"] = Accessory
	local Shirt = character:FindFirstChild("Shirt")
	local Pants = character:FindFirstChild("Pants")

	if Shirt then
		data["Shirt"] = Shirt.ShirtTemplate
	end

	if Pants then
		data["Pants"] = Pants.PantsTemplate
	end

	return data
end

local function deserializeData(character, data)
	local AccessorysReceived = data["Accessorys"]

	for _, v in pairs(data) do
		if v:IsA("Accessory") then
			v.Parent = character
		end
	end
	
	if data["Shirt"] then
		local shirt = character:FindFirstChild("Shirt")
		if shirt then
			shirt.ShirtTemplate = data["Shirt"]
		else
			shirt = Instance.new("Shirt")
			shirt.Parent = character
			shirt.ShirtTemplate = data["Shirt"]
		end
	end
	

	if data["Pants"] then
		local pants = character:FindFirstChild("Pants")
		if pants then
			pants.PantsTemplate = data["Pants"]
		else
			pants = Instance.new("Pants")
			pants.Parent = character
			pants.PantsTemplate = data["Pants"]
		end
	end

end

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		
		script.Parent.S.Activated:Connect(function()
			local data = SerializeData(character)
			local success, result = pcall(function()
				return Data:SetAsync("Accessorys_"..player.UserId, data)
				
			end)
		
			if success then
				if result then
					print(result)
				end
			else
				warn(result)
			end
		end)	
		
	end)
end)

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)

		script.Parent.L.Activated:Connect(function()
			
			local data = playersData[player]
			if data then
				deserializeData(character, data)
			end
			
			local success, result = pcall(function()
				return data:GetAsync("Accessorys_"..player.UserId)
			end)
			
			if success then
				if result then
					playersData[player] = result
				end
			else
				warn(result)
			end
			
		end)
	end)
end)
1 Like
-- ServerScriptService
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("PlayerDataStore")

game.Players.PlayerAdded:Connect(function(player)
    local success, data = pcall(function()
        return playerDataStore:GetAsync(player.UserId)
    end)

    if success and data then
        -- Load saved accessories
        if data.accessories then
            for _, accessoryId in ipairs(data.accessories) do
                local accessory = game:GetService("InsertService"):LoadAsset(accessoryId):GetChildren()[1]
                accessory.Parent = player.Character
            end
        end
        
        -- Load saved clothing
        if data.shirtId then
            local shirt = Instance.new("Shirt")
            shirt.ShirtTemplate = "rbxassetid://" .. data.shirtId
            shirt.Parent = player.Character
        end
        
        if data.pantsId then
            local pants = Instance.new("Pants")
            pants.PantsTemplate = "rbxassetid://" .. data.pantsId
            pants.Parent = player.Character
        end
    end
end)

game.Players.PlayerRemoving:Connect(function(player)
    local accessories = {}
    for _, accessory in ipairs(player.Character:GetChildren()) do
        if accessory:IsA("Accessory") then
            table.insert(accessories, accessory:FindFirstChild("Handle").AccessoryType)
        end
    end
    
    local shirt = player.Character:FindFirstChildOfClass("Shirt")
    local pants = player.Character:FindFirstChildOfClass("Pants")

    local playerData = {
        accessories = accessories,
        shirtId = shirt and shirt.ShirtTemplate:match("%d+"),
        pantsId = pants and pants.PantsTemplate:match("%d+")
    }

    local success, errorMessage = pcall(function()
        playerDataStore:SetAsync(player.UserId, playerData)
    end)

    if not success then
        warn("Failed to save player data: " .. errorMessage)
    end
end)

Preferably I would like to have the hats saved via a GUI button, and then the hats loaded in with a different GUI Button instead of leaving (with the clothing ofc to)

1 Like

But I’ll use this as an example/Starter to see what I can do

1 Like

I did a bit of tweaking and im receiving this error. I don’t understand what its trying to find here, but all I can assume is it only accepts a certain string or number.

This is a data restore. I think maybe this is getting a error we have to fix it.

1 Like

So how can we approach this error to fixing it?

1 Like

It looks like you’re working with Roblox’s DataStoreService and encountering an error when trying to store a dictionary. Data stores in Roblox can only store valid UTF-8 encoded data, meaning you need to ensure the data being stored is properly formatted.

Here’s a basic guide to properly encode and store a dictionary in a DataStore:

  1. Serialize the Dictionary to a JSON String:

    • Use HttpService:JSONEncode() to convert the dictionary to a JSON string before storing it.
    • Use HttpService:JSONDecode() to convert the JSON string back to a dictionary when retrieving it.
  2. Example Script:

First, ensure HttpService is enabled in your game. Go to Game SettingsSecurity and enable Allow HTTP Requests.

local DataStoreService = game:GetService("DataStoreService")
local HttpService = game:GetService("HttpService")

local playerDataStore = DataStoreService:GetDataStore("PlayerDataStore")

-- Function to save player data
local function savePlayerData(player)
    local playerData = {
        Health = player.Character.Humanoid.Health,
        Position = player.Character.HumanoidRootPart.Position,
        Inventory = {} -- Example inventory data
    }

    -- Convert the playerData dictionary to a JSON string
    local success, encodedData = pcall(function()
        return HttpService:JSONEncode(playerData)
    end)

    if success then
        local userId = player.UserId
        local saveSuccess, errorMessage = pcall(function()
            playerDataStore:SetAsync(userId, encodedData)
        end)

        if not saveSuccess then
            warn("Failed to save player data: " .. errorMessage)
        end
    else
        warn("Failed to encode player data: " .. encodedData)
    end
end

-- Function to load player data
local function loadPlayerData(player)
    local userId = player.UserId

    local success, storedData = pcall(function()
        return playerDataStore:GetAsync(userId)
    end)

    if success then
        if storedData then
            -- Convert the JSON string back to a dictionary
            local successDecode, decodedData = pcall(function()
                return HttpService:JSONDecode(storedData)
            end)

            if successDecode then
                -- Apply the loaded data to the player
                player.Character.Humanoid.Health = decodedData.Health
                player.Character.HumanoidRootPart.Position = decodedData.Position
                -- Load other player data as needed
            else
                warn("Failed to decode player data: " .. decodedData)
            end
        else
            print("No data found for player.")
        end
    else
        warn("Failed to load player data: " .. storedData)
    end
end

-- Example event handlers for player joining and leaving
game.Players.PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function()
        loadPlayerData(player)
    end)
end)

game.Players.PlayerRemoving:Connect(function(player)
    savePlayerData(player)
end)

Explanation:

  1. HttpService:JSONEncode(playerData) converts the playerData dictionary to a JSON string.
  2. HttpService:JSONDecode(storedData) converts the JSON string back to a dictionary when loading data.
  3. pcall is used to handle any errors that might occur during encoding, decoding, or data store operations.

By using this method, you can ensure the data being stored is in a valid UTF-8 format, avoiding the CantStoreValue error.

  1. DataStoreService already encodes/decodes into JSON/Lua, there is no need to do this step.
  2. The reason why the code provided is giving an error is because it cannot serialize AccessoryType.

image

So I removed the AccessoryType function and just made it so it could gather just the Accessory Handle.

I proceed to ran the code again and its still giving me the same error.

Cannot believe script about sorry I can’t help you datestore

Boost, as im still lost and I’ve tried numerous tweaks but nothing so far.

I’ve changed it so far and here it is.

game.ReplicatedStorage.RemoteEvents.Save.OnServerEvent:Connect(function(player)
	local accessories = {}

	local CharacterInfo = game:GetService("Players"):GetCharacterAppearanceInfoAsync(player.UserId)
	
	for _, assets in pairs(player:GetChildren()) do
		if assets:IsA("Accessory") then
			print(assets.Name)
			local Mesh = assets:FindFirstChild("Handle")
			if Mesh then
				table.insert(accessories, tonumber(Mesh.MeshId:match("%d+")))
			end
		end
	end
	
	

	local shirt = player.Character:FindFirstChildOfClass("Shirt")
	local pants = player.Character:FindFirstChildOfClass("Pants")

	local playerData = {
		accessories = accessories,
		shirtId = shirt and tonumber(shirt.ShirtTemplate:match("%d+")),
		pantsId = pants and tonumber(pants.PantsTemplate:match("%d+"))
	}

	local success, errorMessage = pcall(function()
		playerDataStore:SetAsync(tostring(player.UserId), playerData)
		
		print(playerData)
	end)

	if not success then
		warn("Failed to save player data: " .. errorMessage)
	end
end)

No errors but it doesn’t want to get the MeshId’s.

Nevermind I found a way to do it. Thanks for the help though

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.