Hi, I've lately started practising with DataStores; I've been aiming to try and save multiple values at once. So far this has worked; I've now encountered the issue of essential reverse engineering the method in an attempt to re-call the values when loading.
Below is the method of saving, but as I said I'm struggling to reverse this.
Does anybody have any suggestions?
function System.DataSave(Player) local PlayerData = Player:WaitForChild('PlayerData') local Saves = {} Saves.isPlaying = PlayerData.isPlaying.Value local configs = {"CharacterData", "StarShipData", "Unlocked"} for _, config_name in pairs(configs) do local config = PlayerData[config_name] Saves[config_name] = {} for _, ValueObject in pairs(config:GetDescendants()) do Saves[config_name][ValueObject.Name] = ValueObject.Value end end DS1:SetAsync(Player.UserId, Saves) end
I'm assuming your asking how to "retrieve" your values that you've saved, assuming you've said you want to "restore" these values to their ObjectValue form.
First, you'll want to have a function that can get the data of a player.
function System.LoadData(player) local key = player.UserId end
Next, you'll want to use the method :GetAsync()
to retrieve the values stored with that key.
function System.LoadData(player) local key = player.UserId local playerData = DS1:GetAsync(key) -- retrieve their saved data end
You'll most likely want to check if that data exists, so you can apply default data settings if you wish to. I'll leave that section up to you however.
function System.LoadData(player) local key = player.UserId local playerData = DS1:GetAsync(key) if playerData then -- load and create things like leaderstats here return playerData -- return the player data if you want else -- player has no data, what will you do? -- perhaps create the default save end end
This is an example where you'd be able to create ObjectValues from saved data following your method of doing things.
function System.LoadData(player) local key = player.UserId local playerData = DS1:GetAsync(key) if playerData then local data = Instance.new("Folder") data.Name = "PlayerData" local coins = Instance.new("NumberValue") coins.Value = playerData.Coins -- sets the value of tangible data to what has been saved data.Parent = player coins.Parent = data return playerData else -- player has no data, what will you do? -- perhaps create the default save end end
well first up, Datastore won't save an array or an object, it will cause an error..
so before you save either an array or table, you must turn it into a string, or somehow into binary numbers...
you can use the JSONEncode()
and JSONDecode()
methods of HTTPService
to turn arrays and objects into a JSON like string..
so when you do:
local HTTPService = game:GetService("HTTPService") local data = { coins = 20, wins = 40, swords = {"Katana", "Blackstar", "etc"} } local stringified = HTTPService:JSONEncode(data); print(stringified) -->{ "coins"=20, "wins"=40, "swords"=["Katana", "Blackstar", "etc"] }; local back_to_lua_object = HTTPService:JSONDecode(stringified) -- back to the object that was encoded
you can store the stringified
JSON string in Datastore,
also i recommend that you make a ModuleScript
that handles datastore, this way so everything remains abstract...
like this:
local DatstoreService = game:GetService("DatastoreService") local DS = {}; function DS.initiate(player) local datastore = DatstoreService :GetDataStore(game_ds_key, player.UserId) return { function get_data(key) return datastore:GetAsync(key) end, function set_data(key, value) datastore:SetAsync(key, value) end, function update_data(key, new_value) datastore:UpdateAsync(key, function(old_value) return new_value end) end, function delete_data(key) datastore:RemoveAsync(key); end } end return DS;
so you can just to:
local ds= require(the_datastore_module_script_directory).initiate(player); ds.set_data("some_name_of_data", stringified); ds.get_data("some_name_of_data");