RbxWeb Tutorial

RbxWeb is a DataStore module made by movsb.

by pobammer

Author Avatar

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.