How to approach datastore2 usage for class properties

Hi everyone!

I recently began using datastore2 for my project. I use a playerData ‘class’ for storing player data. Some of this data is required to be shown on the leaderboard, hence the leaderstats. I’m curious whether my approach regarding the datastore2 integration is good or not.

I currently use the OnUpdate event of the datastore2 module to attach the actual property to the datastore, so when the datastore is changed, so does the property. Is there a better way to do this?
Edit: Or is it better to save the whole table in 1 store?

The ‘…’ in the code sample below indicates that there’s more code there that’s not important to the post.

...
local DataStore2 = require(game:Getservice("ServerScriptService").DataStore2)

local PlayerData = {}
PlayerData.__index = PlayerData

DataStore2.Combine("DATA", "level", "points", "exp")

function PlayerData.new(player)
	local levelStore = DataStore2("level", player)
	local pointStore = DataStore2("points", player)
	local expStore = DataStore2("exp", player)
    ... -- more of the same thing
	
	local self = {
		level = levelStore:Get(1),
		points = pointStore:Get(0),
		exp = expStore:Get(0),
        ... -- More properties
	}
	
    -- Leaderstats for 2 visible values on the leaderboard
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	
	local levelStat = Instance.new("NumberValue")
	levelStat.Name = "Level"
	levelStat.Value = self.level
	levelStat.Parent = leaderstats
	
	local pointsStat = Instance.new("NumberValue")
	pointsStat.Name = "Points"
	pointsStat.Value = self.points
	pointsStat.Parent = leaderstats
	
	leaderstats.Parent = player
	
    -- Update class properties when updating the datastore
	levelStore:OnUpdate(function(newLevel)
		levelStat.Value = newLevel
		self.level = newLevel
	end)
	
	pointStore:OnUpdate(function(newPoints)
		pointsStat.Value = newPoints
		self.exp = newPoints
	end)
	
	expStore:OnUpdate(function(newExp)
		self.exp = newExp
	end)

    -- More OnUpdate's for each property that must be saved
	
	setmetatable(self, PlayerData)
	return self
end

-- Example function as to how I would integrate datastore2
function PlayerData:levelUp()
	local expStore = DataStore2("exp", player)
	local levelStore = DataStore2("level", player)

    levelStore:Increment(1)
    expStore:Set(0)
end

Thanks in advance!

I think you may have overcomplicated things a bit, I am not seeing the utility in your use of OOP on top of DS2. What I’ve done is somewhat similar to what you do, but without the PlayerData class:

local levelStore = DataStore2("level", player)
local levelStat = Instance.new("NumberValue")
levelStat.Name = "Level"
levelStat.Value = levelStore:Get(1)
levelStat.Parent = leaderstats
levelStore:OnUpdate(function(newLevel)
	levelStat.Value = newLevel
end)

You can then just use the DS2 API to change level data in any other script by getting the levelstore object and calling increment on it. There is really not much of a point using classes when using DS2 since DS2 takes care of basically anything you’d use a class for in the first place. Also, in your OnUpdate functions, you’re just changing the value of the variable instead of the value attribute of the number value. Example:

--Your implementation
levelStat = newLevel

--Correct implementation
levelStat.Value = newLevel
2 Likes

Thanks for your answer!

Sorry if I wasn’t clear. I use OOP for the playerdata because it’s used in alot of other scripts. Other (not visible) code for this script in the real project is a bit more complicated, hence the object oriented approach.

edit: Thanks for showing the .value typo, forgot to correct that mistake in the original post :slight_smile:

edit2: You’re right in your explanation now that I think of it. I added the datastore after making the basic logic, that’s why I had an OOP approach, but it’ll probably also work with just the DS2 api thanks! I’ll probably still need some og those classes because I can’t just save whole tables if I can simplify them in the serialization step but I’ll see what I can do.

No problem, also you are able to save tables in DS2 if that’s what you’re referring to in edit2.

local PlayerInv = {}
local InvStore = DataStore2("Inventory", player)
local Inventory = InvStore:Get(PlayerInv)

Doing something like this could benefit from an additional data module to create functions like add item, remove item, etc.

1 Like

Yeah I know. The specific situation I’m in right now is something like this:

  • I can probably remove the playerstats class approach as its just extra bloat basically
  • The playerstats include an inventory, and that’s basically a collection of items (tables). I keep the items in the inventory and not just its Id because of easy access (I don’t have to require the item table in every script that needs an item property) but because of that, I’ll probably need to serialize the inventory (to just a list of ids) first, instead of just saving it.

I saw that there were some serialization options available for the DS2 store so I’ll probably just make an inv store and add those ser/deser functions. But I’m already happy you showed me that the class was not necessary, very stupid that I did not see that sooner :stuck_out_tongue:

1 Like

Okay, sounds like you’ve got it handled. Glad I could help