EzData v2 Module

EzData v2
An easier way to save players data!

Features

  • Multiple Data Stores
  • Easily Save & Load Data
  • Automatically create data objects (ex: leaderstats)

Module
Marketplace

Source:

--> Define Class
local EzData = {}
EzData.__index = EzData

--> Services
local DataStoreService = game:GetService("DataStoreService")

--> Class Methods
function EzData.NewDataStore(DataStoreName: string)
	local Class = {
		["DataStore"] = DataStoreService:GetDataStore(DataStoreName),
	}
	
	return setmetatable(Class, {__index = EzData})
end

function EzData:Save(player: Player, DataTable)
	local succ, err = pcall(function()
		self["DataStore"]:SetAsync(player.UserId, DataTable)
	end)
	
	return succ, err
end

function EzData:ErasePlayerData(player: Player, DefaultDataTable: {}?)
	if DefaultDataTable == nil then
		DefaultDataTable = {}
	end
	
	local succ, err = pcall(function()
		self["DataStore"]:SetAsync(player.UserId, DefaultDataTable)
	end)

	return succ, err
end

function EzData:Load(player: Player, DefaultDataTable: {}?)
	local Data = nil
	
	local Succ, err = pcall(function()
		Data = self["DataStore"]:GetAsync(player.UserId)
	end)
	
	if Data == nil and DefaultDataTable ~= nil and type(DefaultDataTable) == "table" then
		Data = DefaultDataTable
	end
	
	return Data, Succ, err
end

function EzData:CreateDataObjects(player: Player, Data)
	local function load(N, V)
		local function title(s)
			return s:sub(1, 1):upper() .. s:sub(2, #s)
		end

		local _type = type(V)
		local instanceType = _type == "table" and "Folder" or `{title(_type)}Value`
		instanceType = _type == "boolean" and "BoolValue" or instanceType

		local Inst = Instance.new(instanceType)
		
		if instanceType ~= "Folder" then
			Inst.Value = V
		end
		
		Inst.Name = N

		return Inst
	end
	
	local function DigTable(tbl, forceParent)
		for index, v in pairs(tbl) do
			if type(v) == "table" then
				local folder = load(index, v)
				folder.Parent = player
				DigTable(v, folder)
			else
				local inst = load(index, v)

				if forceParent == nil then
					inst.Parent = player
				else
					inst.Parent = forceParent
				end
			end
		end
	end
	
	DigTable(Data)
end

return EzData

Documentation

--[[

-- Requiring the module
local EzData = require(game:GetService("ReplicatedStorage"):WaitForChild("EzData v2"))

-- Creating a data store
local DataStore = EzData.NewDataStore("Test Data Store")

-- Creating a Default Data Table
local DefaultDataTable = {
	["leaderstats"] = {
		["Kills"] = 0,
		["Deaths"] = 0,
	}
}

-- Saving Player Data
DataStore:Save(player: Player, DataTable: {})

-- Loading Player Data
local SavedData: {}, Succ: boolean, Err: string = EzData:Load(player: Player)

-- Erase Player Data
DataStore:ErasePlayerData(player: Player, DefaultDataTable: {})

-- Creating Data Objects
DataStore:CreateDataObjects(player: Player, SavedData: {})

]]--

Example Script

--> Services
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--> Variables
local EzData = require(ReplicatedStorage:WaitForChild("EzData v2"))

local PlayerData = EzData.NewDataStore("Player_Data_1")
local DefaultDataTable = {
	["leaderstats"] = {
		["Deaths"] = 0,
		["Kills"] = 0,
		["Level"] = 1,
	},
	["XP"] = 0,
}


--> Functions
function PlayerAdded(player: Player)
	local SavedData = PlayerData:Load(player, DefaultDataTable)
	PlayerData:CreateDataObjects(player, SavedData)
end

function PlayerRemoving(player: Player)
	local DataTable = {}
	
	local leaderstats = player:FindFirstChild("leaderstats")
	local Deaths = leaderstats:FindFirstChild("Deaths")
	local Kills = leaderstats:FindFirstChild("Kills")
	local Level = leaderstats:FindFirstChild("Level")
	local XP = player:FindFirstChild("XP")
	
	DataTable["leaderstats"] = {
		["Deaths"] = Deaths.Value,
		["Kills"] = Kills.Value,
		["Level"] = Level.Value,
	}
	
	DataTable["XP"] = XP.Value
	
	PlayerData:Save(player, DataTable)
end

--> Connections
Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)

Uncopylocked Game

Feedback
Reply below with any feedback, suggestions or errors!

4 Likes

couldn’t exploiters easily abuse this? Unless your checking all data on the server otherwise I don’t see why they couldn’t

Clients don’t have access to DataStores

Client can’t access the server

Really good module! I just have an idea


Maybe you could use another approach like Datastore:Get
(player) and it returns a metatable that when -, +, *, ^, etc it does it so the example code will be like:

local obj = Datastore:Get(plr)

obj -= 10 -- Will subtract 10 and save it automatically
obj += 10  --  will add 10

 -- Or if it is a a table
 -- using the __index metatable that returns a function you can

obj.insert([[hello]])  -- Will be like table.insert but with a metatable and saves automatically while obj is equal to the Datastore value


I am aware. But if you understood what I am saying which is if theyre sending the data to the server then the server is accepting it without checking then I dont see why the cheaters couldnt modify the values.

I know.

The client can’t send any data to the server. There are no RemoteEvents or RemoteFunctions or any networking library being used.

that is interesting. Ill check this out more.

Quick Question, How does overriding older data for specific values work when using this?

So lets say the user already has some data like Kills and after they get another kill and leave would this override the older value with the newer or add it up?

(Im just a little confused on how this framework works.)

Code:

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

--> Variables
local EzData = require(ReplicatedStorage:WaitForChild("EzData v2"))

local PlayerData = EzData.NewDataStore("UserData")
local DefaultDataTable = {
	["Kills"] = 55, -- we will use 55 as a placeholder for this question
}

--> Functions
function PlayerAdded(player: Player)
	local SavedData = PlayerData:Load(player, DefaultDataTable)
	PlayerData:CreateDataObjects(player, SavedData)
end

function PlayerRemoving(player: Player)
	local DataTable = {}

	local Kills = player:FindFirstChild("Kills")

	DataTable["Kills"] = Kills.Value

	PlayerData:Save(player, DataTable)
end

--> Connections
Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)

Im just a little confused on how the saving works is all.

ezdata need updates more often! I use it but we need more fonctionnality like edit data of an offline player …

you can edit the data of an offline player anyway? Just have the UserId of the user or their key within the ds and you will be able to edit their data lol

There is no point in using this Module. :poop:

It’s just a very basic script that anyone can make.

2 Likes