You don't really have to worry about memory usage since the per-key data limit is quite large (~260000 characters). You can also check the size of the data you're storing by converting the data into a JSON string and calculating its length with the string.len function. You can store any value that can be JSONified.
It really comes down to how your game is set up. If you're storing a player's data as values inside a folder somewhere, simply iterate through it and construct a table. You can then write a function to do the opposite: construct a folder from a data entry for loading the data into the game. For example:
local function buildDataEntryFromFolder(folder)
local dataEntry = {}
for _, valueObject in next, folder:GetChildren() do
if valueObject:IsA("ValueBase") then
dataEntry[valueObject.Name] = {valueType = valueObject.ClassName, value = valueObject.Value}
end
end
return dataEntry
end
local function buildFolderFromDataEntry(dataEntry)
local folder = Instance.new("Folder")
for name, info in next, dataEntry do
local value = Instance.new(info.valueType)
value.Value = info.value
value.Parent = folder
end
return folder
end
local function savePlayerData(player)
local dataEntry = buildDataEntryFromFolder(player.dataFolder)
playerDataStore:SetAsync(player.UserId, dataEntry)
end
local function loadPlayerData(player)
local dataEntry = playerDataStore:GetAsync(player.UserId)
if not dataEntry then
dataEntry = dataTemplate
end
local folder = buildFolderFromDataEntry(dataEntry)
folder.Name = "dataFolder"
folder.Parent = player
return dataEntry, folder
end
The dataTemplate table could look like this:
local dataTemplate = {
kills = {
valueType = "IntValue",
value = 0,
},
deaths = {
valueType = "IntValue",
value = 0,
},
customName = {
valueType = "StringValue",
value = "data-wizard",
},
ownsACoolSword = {
valueType = "BoolValue",
value = false,
},
}
Of course, you could scrap the dataTemplate table and directly clone a pre-built folder structure. There are multiple ways of doing stuff. I personally avoid the value objects all I can and prefer writing my own structures with the functionality I want.
The end result will depend on what kind of data exactly you want to store. The example above doesn't support very organized data-structures as it just throws them all into one table instead of splitting between multiple sub-tables (and -folders), for example.
Anyways, how would I easily save and load the items they already own
You can grab the player data with the "loadPlayerData" function, iterate through the data (this is where the sub-folders would come in handy) , check if they own the item and if so, give it to them.
game.Players.PlayerAdded:Connect(function(player)
local playerData = loadPlayerData(player)
for itemIdentifier, info in next, playerData.items do
if info.value then
giveItem(player, itemIdentifier)
end
end
end)