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)
-- 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)
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.
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:
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.
Example Script:
First, ensure HttpService is enabled in your game. Go to Game Settings → Security 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:
HttpService:JSONEncode(playerData) converts the playerData dictionary to a JSON string.
HttpService:JSONDecode(storedData) converts the JSON string back to a dictionary when loading data.
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.
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.