How to datastore2 more than 1 variable?

I’m new to DataStore2 and I need to store lots of things. I need to store wins, moneys and bunker likes and bunker data but I am still confused on how to do that and also a bit confused on how to load data.

local DataStore2 = require(1936396537) -- I need to change this to the updated one
local ServerStorage = game.ServerStorage
local Workspace = game.Workspace 
local Players = game.Players
local default omega_coins = 0
local default_likes = 0
local default_wins = 0
local default_bunker_terrain_position = {CFrame.new(26.927, -33.383, -435.507), CFrame.new(26.927, 23.365, -572.788), CFrame.new(164.479, 23.365, -434.153), 
CFrame.new(-110.625, 23.365, -435.236), CFrame.new(25.844, 23.365, -297.955)}
local default_bunker_terrain_size = {Vector3.new(277.27, 8.143, 277.27), Vector3.new(277.27, 108.309, 2.708),Vector3.new(2.166, 108.309, 274.562),Vector3.new(2.166, 108.309, 272.396),Vector3.new(275.104, 108.309, 2.166)}
local default_bunker_materials = {"Mud","Rock","Rock","Rock","Rock"}




Players.PlayerAdded:Connect(function(plr)
	local pointsDataStore = DataStore2("Ωmega Coins",plr) -- tried putting more things there but i don't think that is how it works
	
	local leaderstats = Instance.new("Folder",plr) ---leaderstats folder
	leaderstats.Name = "leaderstats"
	
	
	local wins = Instance.new("IntValue",leaderstats)  --leaderstats
	wins.Name = "Wins"
	
	local omega_coins = Instance.new("IntValue",leaderstats)
	omega_coins.Name = "Ωmega $"
	
	local likes = Instance.new("IntValue",leaderstats)
	likes.Name = "Likes"
end)

function save_to_model(folder_name, target_location, xoffset, yoffset, zoffset)
	local newMap = ServerStorage.empty_map:Clone()
	newMap.Name = folder_name
	newMap.Parent = Workspace.maps
	local terrain = newMap.terrain:WaitForChild("cubes")
	
for i, v in pairs(default_bunker_materials) do
	local part = Instance.new("Part")
	part.Name = v
	part.Anchored = true
	part.Transparency = 1

	-- new block:
	part.CFrame = default_bunker_terrain_position[i]
	part.Size = default_bunker_terrain_size[i]

	part.Parent = terrain
end
end

save_to_model("MrGuyROBLOX's Dungeon", game.Workspace.maps,0,0,0)
2 Likes

Your best bet would be to use Datastore2’s combined datastore feature! By doing multiple stores that aren’t combined, you risk throttling and possible data loss. This is the gotcha page detailing it: Gotchas - DataStore2

And this is the API for the combine method: API - DataStore2

When you then retrieve the datastore, you can pull all the info out of the table and separate it using the values you created (as you would if you were to request multiple datastores). Then at the end when you want to set the data, just combine everything back and you should be good to go and can save it!

Ok I saw that post but I don’t fully understand it. It said `DataStore2.Combine("DATA", "any", "keys", "here") but I have no idea what all of those arguments are.

Could you please explain them? :slight_smile:

Does anyone know how

DataStore2.Combine

works? I need an explanation ASAP.

Hi, I’ve just recently gotten into Datastore2 myself, but I believe in your case it’d be something along the lines of

DataStore2.Combine("DATANAME", "Wins", "Ωmega $", "Likes") 

“ any keys here” simply means you can add any keys as I’ve done above

DataStore2.Combine(masterKey, ...keysToCombine) combines all the keys under keysToCombine under the masterKey . Internally, will save all data under those keys into the masterKey as one large dictionary. Saving all your data into one large table minimizes data loss and throttling. DataStore2 makes it so you don’t have to get the entire table if you only want a small part of it.

Taken straight from the DataStore2 API.

I need to store multiple stores of data but I have no idea how to use DataStore2.combine and what Gotchas - DataStore2 and API - DataStore2 means. I tried asking on the original post i made but it is dead all of a sudden.

3 Likes

Well the first argument is the master key. Think of this as the key of keys. The “main” you can say.

The trailing keys are just subkeys.

DataStore2.Combine("main", "coins", "gems", etc)

local function some_function_with_player(player)
    local coins_data = DataStore2("coins", player)
    -- etc
end

You get the "coins" stat. And the "coins", and any other keys you add will be under "main".

1 Like

DataStore2.Combine() takes as its first argument the name of the master datastore, so internally it will be using only one master datastore, its name being what you gave as the first argument. All the following arguments should be the names of the datastores you wish to combine.

What’s nice about this is that you can treat each key of the combined datastore as it’s own datastore, making saving data easier, you don’t need to consolidate data each save, you give partial data, DataStore2 makes it whole.
This is especially well shown in the Basic Usage example:

local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")

local DataStore2 = require(ServerScriptService.DataStore2)

-- Combine the keys we wish to use as their own datastores later
DataStore2.Combine("DATA", "coins")

Players.PlayerAdded:Connect(function(player)
    local coinStore = DataStore2("coins", player) -- Notice how this isn't a separate datastore but you can treat it as one


    local function callRemote(value)
        ReplicatedStorage.CoinAmount:FireClient(player, value)
    end

    -- Fire a remote event to the player telling them how many coins they have.
    -- If this is their first time playing the game, they'll start out with 100.
    callRemote(coinStore:Get(100))

    -- Everytime the coin store updates, we'll send the RemoteEvent again.
    coinStore:OnUpdate(callRemote)
end)

You can find examples on the Basic Usage page and check out the API reference itself.

Ok here is my script. 63 lines

local DataStore2 = require(1936396537)
local ServerStorage = game.ServerStorage
local Workspace = game.Workspace 
local Players = game.Players
local default omega_coins = 0
local default_likes = 0
local default_wins = 0
local default_bunker_terrain_position = {CFrame.new(26.927, -33.383, -435.507), CFrame.new(26.927, 23.365, -572.788), CFrame.new(164.479, 23.365, -434.153), 
CFrame.new(-110.625, 23.365, -435.236), CFrame.new(25.844, 23.365, -297.955)}
local default_bunker_terrain_size = {Vector3.new(277.27, 8.143, 277.27), Vector3.new(277.27, 108.309, 2.708),Vector3.new(2.166, 108.309, 274.562),Vector3.new(2.166, 108.309, 272.396),Vector3.new(275.104, 108.309, 2.166)}
local default_bunker_materials = {"Mud","Rock","Rock","Rock","Rock"}


DataStore2.Combine("main", "Wins", "Ωmega Coins", "Likes", "object_name", "object_position", "object_rotation", "terrain-position", "terrain_rotation", "terrain_size", "terrain_materials")

Players.PlayerAdded:Connect(function(plr)
local winsStore = DataStore2("Wins", plr)
local coinStore = DataStore2("Ωmega Coins", plr)
local likesStore = DataStore2("Likes", plr)
local objectnameStore = DataStore2("object_name", plr)
local objectpositionStore = DataStore2("object_position", plr)
local objectrotationStore = DataStore2("object_rotation", plr)
local terrainpositionStore = DataStore2("terrain-position", plr)
local terrainrotationStore = DataStore2("terrain_rotation", plr)
local terrainsizeStore = DataStore2("terrain_size", plr)
local terrainmaterialsStore = DataStore2("terrain_materials", plr)
 	
	
	local leaderstats = Instance.new("Folder",plr) ---leaderstats folder
	leaderstats.Name = "leaderstats"
	
	
	local wins = Instance.new("IntValue",leaderstats)  --leaderstats
	wins.Name = "Wins"
	
	local omega_coins = Instance.new("IntValue",leaderstats)
	omega_coins.Name = "Ωmega $"
	
	local likes = Instance.new("IntValue",leaderstats)
	likes.Name = "Likes"
end)



function save_to_model(folder_name, target_location, CFrameoffset)
	local newMap = ServerStorage.empty_map:Clone()
	newMap.Name = folder_name
	newMap.Parent = Workspace
	local terrain = newMap.terrain:WaitForChild("cubes")
	
for i, v in pairs(default_bunker_materials) do
	local part = Instance.new("Part")
	part.Name = v

	-- new block:
	part.CFrame = default_bunker_terrain_position[i]
	part.Size = default_bunker_terrain_size[i]

	part.Parent = terrain
end
end

save_to_model("MrGuyROBLOX's Dungeon", game.Workspace.maps,0,0,0)

I need to save the default array for the bunker properties or load the saved data if there is data (terrain rotation is unused at the moment) and make sure that the data is visible to the save_to_model function. I have been using the default value for testing purposes at the moment

Can this topic please not die before I solve the issue thanks.

I am trying to load the variable default_bunker_terrain_position with DataStore2:Get(default_bunker_terrain_position) but I get an error when the script gets to that line (48)

13:33:37.674 - ServerScriptService.save_script:48: attempt to call a nil value

Script:

local DataStore2 = require(1936396537) -- Don't mind this I will fix it later
local ServerStorage = game.ServerStorage
local Workspace = game.Workspace 
local Players = game.Players
local default_omega_coins = 0
local default_likes = 0
local default_wins = 0
local default_bunker_terrain_position = {CFrame.new(26.927, -33.383, -435.507), CFrame.new(26.927, 23.365, -572.788), CFrame.new(164.479, 23.365, -434.153), 
CFrame.new(-110.625, 23.365, -435.236), CFrame.new(25.844, 23.365, -297.955)}
local default_bunker_terrain_size = {Vector3.new(277.27, 8.143, 277.27), Vector3.new(277.27, 108.309, 2.708),Vector3.new(2.166, 108.309, 274.562),Vector3.new(2.166, 108.309, 272.396),Vector3.new(275.104, 108.309, 2.166)}
local default_bunker_terrain_rotation = {CFrame.Angles(0,0,0), CFrame.Angles(0,0,0), CFrame.Angles(0,0,0), 
CFrame.Angles(0,0,0), CFrame.Angles(0,0,0)}
local default_bunker_materials = {"Mud","Rock","Rock","Rock","Rock"}


DataStore2.Combine("main", "Wins", "Ωmega Coins", "Likes", "object_name", "object_position", "object_rotation", "terrain-position", "terrain_rotation", "terrain_size", "terrain_materials")

Players.PlayerAdded:Connect(function(plr)
local winsStore = DataStore2("Wins", plr)
local coinStore = DataStore2("Ωmega Coins", plr)
local likesStore = DataStore2("Likes", plr)
local objectnameStore = DataStore2("object_name", plr)
local objectpositionStore = DataStore2("object_position", plr)
local objectrotationStore = DataStore2("object_rotation", plr)
local terrainpositionStore = DataStore2("terrain-position", plr)
local terrainrotationStore = DataStore2("terrain_rotation", plr)
local terrainsizeStore = DataStore2("terrain_size", plr)
local terrainmaterialsStore = DataStore2("terrain_materials", plr)
 	
	
	local leaderstats = Instance.new("Folder",plr) ---leaderstats folder
	leaderstats.Name = "leaderstats"
	
	
	local wins = Instance.new("IntValue",leaderstats)  --leaderstats
	wins.Name = "Wins"
	
	local omega_coins = Instance.new("IntValue",leaderstats)
	omega_coins.Name = "Ωmega $"
	
	local likes = Instance.new("IntValue",leaderstats)
	likes.Name = "Likes"
end)



function save_to_model(folder_name, target_location, CFrameoffset)
	DataStore2:Get(default_bunker_terrain_position) 
	
	local newMap = ServerStorage.empty_map:Clone()
	newMap.Name = folder_name
	newMap.Parent = Workspace
	local terrain = newMap.terrain:WaitForChild("cubes")
	
for i, v in pairs(default_bunker_materials) do
	local part = Instance.new("Part")
	part.Name = v

	-- new block:
	part.CFrame = default_bunker_terrain_position[i]
	part.Size = default_bunker_terrain_size[i]

	part.Parent = terrain
end
end

save_to_model("MrGuyROBLOX's Dungeon", game.Workspace.maps,0,0,0)

I just now thought maybe I there is a problem with my thing that sets the default value and that’s why it is nil but maybe not.

You need to call :Get on a Datastore, not the module itself. See the docs here: API - DataStore2

2 Likes

I should use :GetTable instead of :Get right? default_bunker_terrain_position is a table.

You just need a datastore object. Like the API says, some functions are methods of Datastore2 (the module) and some are methods of Datastore (a datastore object). You’re trying to call it on the module, which doesn’t work.

There’s a note under GetTable saying it’s not necessary:

This is not necessary to use tables with DataStore2. You can save/retrieve tables just like any other piece of data.

2 Likes

Ok I have been trying to do terrainpositionStore:Get()

But it won’t recognise the variable. I changed all the variables below to global

Players.PlayerAdded:Connect(function(plr)

winsStore = DataStore2("Wins", plr)

coinStore = DataStore2("Ωmega Coins", plr)

likesStore = DataStore2("Likes", plr)

objectnameStore = DataStore2("object_name", plr)

objectpositionStore = DataStore2("object_position", plr)

objectrotationStore = DataStore2("object_rotation", plr)

terrainpositionStore = DataStore2("terrain-position", plr)  -- Doesn't recognize this???

terrainrotationStore = DataStore2("terrain_rotation", plr)

terrainsizeStore = DataStore2("terrain_size", plr)

terrainmaterialsStore = DataStore2("terrain_materials", plr)

Datastore2 is defined for each player, but your code is probably running before any players join. If this isn’t specifically supposed to be saved to a player’s datastore, this shouldn’t really be using DataStore2. If it should be saved to a player’s datastore, you should probably be keeping track of each datastore per player and getting that specific player’s datastore when you call save_to_model.

2 Likes

Yep I am saving it to each specific player. I don’t know how to keep track of each datastore per player though.

Your variables earlier were in different scopes. Through terrainpositionStore:Get(default_bunker_terrain_position) in a function you were trying to access terrainpositionStore which is in the PlayerAdded event. To fix this, you can put the function save_to_model() inside the PlayerAdded event Connect()ion.

Also, I noticed in the end you were calling

just once at the end of the script. If each player has their own bunker terrain position, then you’re going to have to do this for every single player, which means you could put it in the PlayerAdded event. Make sure, however, that if you’re accessing the folders later, that you name them something unique, something based on the name of the player.
(Instead of “MrGuyROBLOX’s Dungeon”, try plr.Name .. "'s Dungeon")

The function call at the end is for testing purposes.

Updated the script before you made the post btw

local DataStore2 = require(1936396537) -- Don't mind this I will fix it later
local ServerStorage = game.ServerStorage
local Workspace = game.Workspace 
local Players = game.Players
local default_omega_coins = 0
local default_likes = 0
local default_wins = 0
local default_bunker_terrain_position = {CFrame.new(26.927, -33.383, -435.507), CFrame.new(26.927, 23.365, -572.788), CFrame.new(164.479, 23.365, -434.153), 
CFrame.new(-110.625, 23.365, -435.236), CFrame.new(25.844, 23.365, -297.955)}
local default_bunker_terrain_size = {Vector3.new(277.27, 8.143, 277.27), Vector3.new(277.27, 108.309, 2.708),Vector3.new(2.166, 108.309, 274.562),Vector3.new(2.166, 108.309, 272.396),Vector3.new(275.104, 108.309, 2.166)}
local default_bunker_terrain_rotation = {CFrame.Angles(0,0,0), CFrame.Angles(0,0,0), CFrame.Angles(0,0,0), 
CFrame.Angles(0,0,0), CFrame.Angles(0,0,0)}
local default_bunker_materials = {"Mud","Rock","Rock","Rock","Rock"}
local default_object_name = {}
local default_object_position = {}
local default_object_rotation = {}


DataStore2.Combine("main", "Wins", "Ωmega Coins", "Likes", "object_name", "object_position", "object_rotation", "terrain-position", "terrain_rotation", "terrain_size", "terrain_materials")

Players.PlayerAdded:Connect(function(plr)
winsStore = DataStore2("Wins", plr)
coinStore = DataStore2("Ωmega Coins", plr)
likesStore = DataStore2("Likes", plr)
objectnameStore = DataStore2("object_name", plr)
objectpositionStore = DataStore2("object_position", plr)
objectrotationStore = DataStore2("object_rotation", plr)
terrainpositionStore = DataStore2("terrain-position", plr)
terrainrotationStore = DataStore2("terrain_rotation", plr)
terrainsizeStore = DataStore2("terrain_size", plr)
terrainmaterialsStore = DataStore2("terrain_materials", plr)
 	
	
	local leaderstats = Instance.new("Folder",plr) ---leaderstats folder
	leaderstats.Name = "leaderstats"
	
	
	local wins = Instance.new("IntValue",leaderstats)  --leaderstats
	wins.Name = "Wins"
	
	local omega_coins = Instance.new("IntValue",leaderstats)
	omega_coins.Name = "Ωmega $"
	
	local likes = Instance.new("IntValue",leaderstats)
	likes.Name = "Likes"
	
if terrainpositionStore == nil then
	terrainpositionStore = default_bunker_terrain_position
end
if terrainmaterialsStore == nil then
	terrainmaterialsStore = default_bunker_materials
end
if terrainrotationStore == nil then
	terrainrotationStore = default_bunker_terrain_rotation
end
if terrainsizeStore == nil then
	terrainsizeStore = default_bunker_terrain_size
end
if objectnameStore == nil then
	objectnameStore = default_object_name
end
if objectpositionStore == nil then
	objectpositionStore = default_object_position
end
if objectrotationStore == nil then
	objectrotationStore = default_object_rotation
end
if winsStore == nil then
	terrainpositionStore = default_wins
end
if coinStore == nil then
	coinStore = default_omega_coins
end
if likesStore == nil then
	likesStore = default_likes
end
	
end)



function save_to_model(folder_name, target_location, CFrameoffset)
	
	local newMap = ServerStorage.empty_map:Clone()
	newMap.Name = folder_name
	newMap.Parent = Workspace
	local terrain = newMap.terrain:WaitForChild("cubes")
	
for i, v in pairs(default_bunker_materials) do
	local part = Instance.new("Part")
	part.Name = v

	-- new block:
	part.CFrame = terrainpositionStore[i]
	part.Size = default_bunker_terrain_size[i]

	part.Parent = terrain
end
end

save_to_model("MrGuyROBLOX's Dungeon", game.Workspace.maps,0,0,0)

I couldn’t imagine using that much code for datastores honestly, and are you using the latest version of DS2 from GitHub?