DataStore Not working

Hello, so I am trying to make a saving thing for players hats and stuff to save when they leave and rejoin, I have no idea how to make this, but I am currently just testing stuff and I got this error
image
here is my code

local DataStoreService = game:GetService("DataStoreService")
local ClothingData = DataStoreService:GetDataStore("ClothingSave")

game.Players.PlayerAdded:Connect(function(LocalPlayer)
	LocalPlayer.CharacterAppearanceLoaded:Connect(function(character)
		local hats = character:WaitForChild("Humanoid"):GetAccessories()
		local PlayerData
		local success, errormessage = pcall(function()
			PlayerData = ClothingData:GetAsync(LocalPlayer.UserId.."-hats")
		end)
		if success then 
			hats = PlayerData
			print("success")
		else
			warn(errormessage)
		end
	end)
end)

game.Players.PlayerRemoving:Connect(function(LocalPlayer)
	LocalPlayer.CharacterRemoving:Connect(function(Character)
		local hats = Character:WaitForChild("Humanoid"):GetAccessories()
		local success, errormessage = pcall(function()
			ClothingData:SetAsync(LocalPlayer.UserId, hats)
		end)
		if success then
			print("Success")
		else
			warn(errormessage)
		end
	end)
end)
1 Like

GetAccessories returns an array of accessories. Accessories cannot be stored in a datastore. Rather you can store the names of those accessories instead.

1 Like

You can’t save player accessories however you can save your own game accessories.

How could I do this? I have no idea how

You could create a table and use use table.insert I believe to insert their accessory names I can send a few articles that may help you

1 Like

Try this:

local hatsTable = {}
for _, v in ipairs(hats) do
table.insert(hatsTable, v)
end
1 Like

Seems to work great, thank you! Your answer is now marked as solution.

1 Like

I said the same exact thing above but it’s fine I guess

Ok so the problem you’re having is that you cannot save accessories to the datastore. Creating a different table and adding the hats to them is the exact same thing as what you started with (you may not be getting an error because studio doesn’t always have time to save data when the server shuts down).

This would be a WHOLE LOT easier if you could save things other than numbers/strings to the datastore, but if each player is bringing in a new accessory then there’s really no point having every accessory saved to your game permanently, so you will need to use InsertService.

Definitely check the datastore article out

I had to do a few things to get this to work…First I needed to change your SetAsync index; you had the GetAsync set as LocalPlayer.UserId.."-hats" which is fine, but you will need to SetAsync to the same thing. Then, I needed to get the website ID’s for all accessories on the character; you cannot do this with the meshId because it is an AssetId, and will return nothing with InsertService. I used GetCharacterAppearanceInfoAsync() to retrieve the info from the character, then indexed it searching for only accessories (whitelisted asset types stored in assetWhiteList). The function getInfo returns the ID’s of all of the player’s accessories in a table. When a player leaves, the function save() takes the player’s info and userID before it disappears, then sets the datastore to the accessory list returned by getInfo().

When the player joins and there is data, just for example I made the script will delete the players hats, waits 2 seconds and uses the function spawnHats() to use the InsertService to spawn the hats by their ID’s, then use the AddAccessory function to the player’s Humanoid.

Of course you can do whatever you want with this info, but I didn’t know your end goal.

You may notice at the bottom I use game:BindToClose(); this function allows the game to complete datastore saves before shutting down as the last player leaves. This is useful in studio since you are the last person to leave, but will be even more important in-game so that the game doesn’t shut down before data is saved.

All-in-all, I HIGHLY recommend against using a server script for datastores; use a modulescript. Also, make sure to autosave often, because there may be times when a player leaves and their data cannot be saved for one reason or another.

Code:

local DataStoreService = game:GetService("DataStoreService")
local ClothingData = DataStoreService:GetDataStore("ClothingSave")
local InsertService = game:GetService("InsertService")

local assetWhiteList = {
	"Hat",
	"Shoulder Accessory",
	"Waist Accessory",
	"Hair Accessory",
	"Back Accessory",
	"Face Accessory",
	"Front Accessory"
}

function save(LocalPlayer)
	local info = game.Players:GetCharacterAppearanceInfoAsync(LocalPlayer.UserId)
	local userId = LocalPlayer.UserId
		
	local success, errormessage = pcall(function()
		ClothingData:SetAsync(LocalPlayer.UserId.."-hats", getInfo(userId, info))
	end)
	if success then
		print("Success")
	else
		warn(errormessage)
	end
	
end

function getInfo(userId, info)
	if not info then
		info = game.Players:GetCharacterAppearanceInfoAsync(userId)
	end
	
	local accessoryIdList = {
	}
	for i,v in ipairs(info['assets']) do
		local whiteListed = false
		for index, item in ipairs(assetWhiteList) do
			if item == v.assetType.name then
				whiteListed = true
			end
		end
		if whiteListed then
			local AssetId = v.id
			table.insert(accessoryIdList, AssetId)
		end
	end
	return accessoryIdList
end

function spawnHats(LocalPlayer, hats)
	for i, v in ipairs(hats) do

		local success, model = pcall(InsertService.LoadAsset, InsertService, v)
		if success and model then
			print("Model loaded successfully")
			model.Parent = game.Lighting
			LocalPlayer.Character:WaitForChild("Humanoid"):AddAccessory(model:FindFirstChildOfClass('Accessory'))
			model:Remove()
		else
			print("Model failed to load!")
		end
	end
end

game.Players.PlayerAdded:Connect(function(LocalPlayer)
	LocalPlayer.CharacterAppearanceLoaded:Connect(function(character)
		local PlayerData
		local success, data = pcall(function()
			PlayerData = ClothingData:GetAsync(LocalPlayer.UserId.."-hats")
			return PlayerData
		end)
		if data then --previous hat data exists
			
			PlayerData = data
			
			character:WaitForChild('Humanoid'):RemoveAccessories()
			wait(2)
			spawnHats(LocalPlayer, PlayerData)
			
			print("success")
		else
			warn(data)
		end
	end)
end)

game.Players.PlayerRemoving:Connect(function(LocalPlayer)
	
	save(LocalPlayer)
	
end)

game:BindToClose(function()
	for _, LocalPlayer in ipairs(game:GetService('Players'):GetPlayers()) do
		save(LocalPlayer)
		print('done')
	end
end)