Hard Written By howmanysmaII

RbxWeb Tutorial Created on: 19-07-2019

RbxWeb is a DataStore module made by movsb.

Welcome back to another tutorial. Today I'll be showing you how to use RbxWeb, which is a DataStoreService wrapper made by my friend movsb. I'll be using a rewritten version of it, so that it's more similar to the actual DataStoreService.

To get things started, let's require the module in our Main script.

local RbxWeb = require(3254046154)

Now that we have that, we need to initialize the module. You can either use MockDataStoreService made by buildthomas by passing the require function, or use the default DataStoreService by passing game. I'm gonna be using require because it's just easier that way and allows pseudo-DataStores on local files.

local RbxWeb = require(3254046154)
RbxWeb:Initialize(require)

We should also setup our services and whatnot. The script should look like this afterwards.

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

local RbxWeb = require(3254046154)
RbxWeb:Initialize(require)

Now, we're gonna get a generic DataStore (which is just another name for GlobalDataStore). To do this, we have to call two functions, AddGeneric and GetGeneric.

The API for these functions are as follows:

>RbxWeb::AddGeneric(string Key, string Scope, string Prefix: ""): GlobalDataStore RbxWeb::GetGeneric(GlobalDataStore DataRoot): GenericClass

Here's how I usually do it:

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

local RbxWeb = require(3254046154)
RbxWeb:Initialize(require)

local VERSION = "V1"

local GameDataStore = RbxWeb:GetGeneric(RbxWeb:AddGeneric(
	"GameDataStore" .. (RunService:IsStudio() and "Testing" or "Release") .. VERSION,
	"Global",
	"PlayerData"
))

This will allow us to have separate DataStores depending on if you're testing the game or not. Now, we're gonna setup our PlayerAdded and PlayerRemoving connections.

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

local RbxWeb = require(3254046154)
RbxWeb:Initialize(require)

local VERSION = "V1"

local GameDataStore = RbxWeb:GetGeneric(RbxWeb:AddGeneric(
	"GameDataStore" .. (RunService:IsStudio() and "Testing" or "Release") .. VERSION,
	"Global",
	"PlayerData"
))

local function PlayerAdded(Player)
end

local function PlayerRemoving(Player)
end

Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)

I like to avoid calling DataStore methods too often, as I've had issues with that in the past and it results in data loss, and that's just a pain. The most I suggest is calling GetAsync once in PlayerAdded, and SetAsync if their data is null, and calling GetAsync once more in PlayerRemoving, followed by UpdateAsync. We should set that up now, along with a data template table.

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

local RbxWeb = require(3254046154)
RbxWeb:Initialize(require)

local VERSION = "V1"

local DATA_TEMPLATE = {
	DataID = 0;
	Points = 0;
}

local GameDataStore = RbxWeb:GetGeneric(RbxWeb:AddGeneric(
	"GameDataStore" .. (RunService:IsStudio() and "Testing" or "Release") .. VERSION,
	"Global",
	"PlayerData"
))

local function PlayerAdded(Player)
	local PlayerKey = GameDataStore:GetKey(Player.UserId)
	local Success, PlayerData = GameDataStore:GetAsync(PlayerKey)
	
	if Success and not PlayerData then
		PlayerData = DATA_TEMPLATE
		GameDataStore:SetAsync(PlayerKey, PlayerData)
	end
end

local function PlayerRemoving(Player)
end

Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)

Now that we have that done, we should probably create the Leaderstats for the player, so we can finish up PlayerRemoving.

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

local RbxWeb = require(3254046154)
RbxWeb:Initialize(require)

local VERSION = "V1"

local DATA_TEMPLATE = {
	DataID = 0;
	Points = 0;
}

local GameDataStore = RbxWeb:GetGeneric(RbxWeb:AddGeneric(
	"GameDataStore" .. (RunService:IsStudio() and "Testing" or "Release") .. VERSION,
	"Global",
	"PlayerData"
))

local function PlayerAdded(Player)
	local PlayerKey = GameDataStore:GetKey(Player.UserId)
	local Success, PlayerData = GameDataStore:GetAsync(PlayerKey)
	
	if Success and not PlayerData then
		PlayerData = DATA_TEMPLATE
		GameDataStore:SetAsync(PlayerKey, PlayerData)
	end
	
	local Leaderstats = Instance.new("Folder")
	Leaderstats.Name = "leaderstats"
	Leaderstats.Parent = Player
	
	local Points = Instance.new("IntValue")
	Points.Name = "Points"
	Points.Value = PlayerData.Points
	Points.Parent = Leaderstats
end

local function PlayerRemoving(Player)
	local Leaderstats = Player:FindFirstChild("leaderstats")
	if Leaderstats then
	end
end

Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)

Note: I don't suggest using Leaderstats or ValueBase objects, and instead use a table. If requested enough, I'll show how that can be accomplished.

Now that we have that all done, let's finish our PlayerRemoving function. We're gonna call GetAsync once and then finish it up with UpdateAsync.

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

local RbxWeb = require(3254046154)
RbxWeb:Initialize(require)

local VERSION = "V1"

local DATA_TEMPLATE = {
	DataID = 0;
	Points = 0;
}

local GameDataStore = RbxWeb:GetGeneric(RbxWeb:AddGeneric(
	"GameDataStore" .. (RunService:IsStudio() and "Testing" or "Release") .. VERSION,
	"Global",
	"PlayerData"
))

local function PlayerAdded(Player)
	local PlayerKey = GameDataStore:GetKey(Player.UserId)
	local Success, PlayerData = GameDataStore:GetAsync(PlayerKey)
	
	if Success and not PlayerData then
		PlayerData = DATA_TEMPLATE
		GameDataStore:SetAsync(PlayerKey, PlayerData)
	end
	
	local Leaderstats = Instance.new("Folder")
	Leaderstats.Name = "leaderstats"
	Leaderstats.Parent = Player
	
	local Points = Instance.new("IntValue")
	Points.Name = "Points"
	Points.Value = PlayerData.Points
	Points.Parent = Leaderstats
end

local function PlayerRemoving(Player)
	local Leaderstats = Player:FindFirstChild("leaderstats")
	if Leaderstats then
		local PlayerKey = GameDataStore:GetKey(Player.UserId)
		local Success, PlayerData = GameDataStore:GetAsync(PlayerKey)
		
		if Success and PlayerData then
			GameDataStore:UpdateAsync(PlayerKey, function(OldData)
				local PreviousData = OldData or DEFAULT_DATA
				if PlayerData.DataID == PreviousData.DataID then
					PlayerData.DataID = PlayerData.DataID + 1
					PlayerData.Points = Leaderstats.Points.Value
					
					return PlayerData
				else
					-- Don't save and lose data!
					return nil
				end
			end)
		end
	end
end

Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)

That's basically how to use RbxWeb. It's definitely my favorite module, since it's so much easier to use, and I haven't ever had data loss with it in any of my games.

Hard Written By howmanysmaII

See howmanysmaII's profile on Roblox

Discussion