Using one datastore to save multiple tables?

Hey all!

I am wondering what would be the best way to save for my game I am working on. Players have multiple currencies, and folders of items that they keep. I want to narrow this down to 1 datastore if possible.

In previous games, I have made a new datastore for mostly everything and when saving items I used tables like this:

local save = {}

for i,v in pairs(game.Players.Player.Items:GetChildren()) do
table.insert(save, v.Name)
end

datastore:SetAsync(key, save)

Then I would have one big table saving all of the players number data.

However this created for some huge problems, my datastore queue would become full and players would be losing data left and right as a result of my saving system.

I was wondering, what is the best way to save when you have multiple folders full of items, and number values like cash and exp that you are saving?

4 Likes

FOREWORD: When you’re posting snippets of code, please enclose them within a code block so it’s easier for us to read. You can achieve this by placing three back ticks before and after your code.

```
– Code here
```


I’m not quite sure I understand what you’re attempting to achieve. The title states that you’re attempting to save multiple tables to a data store (key?)… what does this mean? Does your model look like

A:

Key Value
Key1 {data1, data2}

or

B:

Key Value
Key1 {data1, {data2, data3}}

Really, you can accomplish this in any number of ways so long as it works.

One method you can choose to use is to split your data between different scopes. Scoping is basically the same as establishing a whole new data store for data, except you’re only changing where it’s coming from. Think of it like subfolders of a bigger folder.

Where you could have

DataStoreService:GetDataStore("MainData")
DataStoreService:GetDataStore("InventoryData")
DataStoreService:GetDataStore("thisisgross")

You could have

DataStoreService:GetDataStore("Data", "Main")
DataStoreService:GetDataStore("Data", "Inventory")
DataStoreService:GetDataStore("Data", "thisonlylooksgoodifyoudoitright")

The second thing you could do is just everything in a table itself. Where a singular table would represent your entire data structure, subtables would represent the various folders that your data is organised in. Every folder name should be a key and the value should be a table including more key-value pairs representing the name and value of a data item.

Key Value
Data1 {[“Level”] = 1, [“Yes”] = {[“No”] = “Yes”}}
7 Likes

I think what I am trying to get at here is I want to reduce the amount of datastores I am using so that when I use :GetAsync() and :SetAsync() I am not pushing the limit for datstores.

It seemed I was a little broad in my original post, let me reiterate what I am trying to do and maybe that will help. In my game, players have a variety of datapoints like Cash, Experience, Level, etc. They can also buy items from the shop. The items they purchase from the shop, are stored in a folder inside the player. Since I have multiple categories in the shop this ends up being around 6 folders that I am trying to save.

I want to know if I can condense the 6 folders into one datastore, so when I use :GetAsync() I am getting a table that I can read all 6 from, while still keeping them seperately. Does JSONEncode do anything like this?

1 Like

See:

Yes, you can JSONEncode your table if that’s necessary.

I’m not too sure how you’re conscious of hitting data limits, you should be able to save everything. What does your physical data structure look like? (i.e. how it looks in the explorer view)

Seems like you may have just solved my whole question.

When I am loading it in, I can just check each folder for which item it is in, then place it appropriately. You are insanely smart, thank you for helping me realize I can just do it without having to mess with the datastores!

1 Like

I’ve done multiple-folder data saving before. Usually I’d save tables and sub-tables, but I was feeling lazy so I only compiled data into a single layer and saved it that way. No value ever had the same name as another and if it did have to have one, there was explicit changes in the name so I could do that.

Every key-value pair was saved into a single table which was passed over to the data store. When I fetch such data, I use a recursive function to check if the key exists as a physical value object in the primary data prefab - if it does, then the value is set.

How my data would look:

  • Data
    • Key = A, Value = 1
    • Key = B, Value = 2
    • Key = CA, Value = 3
    • Key = CB, Value = 4

How the folders would look:

  • PlayerData
    • A
    • CB
    • Folder
      • B
      • CA

Hopefully that’s understandable.

1 Like

Would you advise me saving things with keys in front (all 3 digit keys) so when I load I can load better?

For example:
Saving the “awesomeredpart” as “parawesomeredpart”, then when I load it in I can do something like:

if string.sub(v, 1, 3) == 'par' then
-- load part
end

If that works for you and you don’t get confused, then by all means go for it. How you set up your code is up to what makes you feel the most comfortable (provided it’s not a group project, in which they’ll specify to you how you should save data - wouldn’t worry too much on that front).

Just if you’re going to add prefixes like that, you’ll want to keep things consistent so your scripts are scalable. If you have a string check that looks at the first three letters of a key, then all your prefixes need to be 3 characters in string length so you can associate them with a folder when establishing player data. Other string methods are available for use if that helps too.

1 Like

Thanks a bunch for your help, means a lot to me. Have a good night/day!

1 Like

In all my games in which I use datastores to store player data, I use an incredibly simple and efficient method.
OAuth2 Table Module
With this Module you can convert Tables into Folders and Folders into Tables, works with subfolders.

When I load I use GetAsync with the UserId of a player, i get a table that I turn into a folder and call it “PlayerData” and put it in the Player, if a player does not have saved data I put a folder with the default data, when I save I convert the folder into a table and I use SetAsync, I hope it helps you, it makes things much easier for me and I only have to write a maximum of 10 lines of code.

7 Likes