Tool persistence

Please don’t call me dumb for this, but I would like to know how do I add/create a Tool Persistence script. First of all, I have a little idea of how datastores work. Now I want to know how can you save two when
1 The player dies, but still keeping the tool.
2 The player leaves the game, but it still saves the tool, automatically or at an interval.

I tried looking at different topics on the Roblox Wiki, I also asked all my friends all about it, but I still have no idea.

Long question short, how do I use datastore/tool persistence to save when the player die/quit the game?

2 Likes

Does every player receive the same set of tools?

No, they would buy items from the shop.

OK. I recommend associating a saved table with each player that describes the tools they possess. When a player joins, we check which tools they own and give them then; similarly, we save any new tools that the player purchases to the data store.

The table will be a dictionary that is structured in a way that allows us to check for elements without iterating through the entire table:

local playerTools = {
    Sword = true,
    Gun = true,
}
-- does player own sword?
print(playerTools.Sword) --> true
-- does player own slingshot?
print(playerTools.Slingshot) --> nil
-- give player slingshot
playerTools.Slingshot = true
print(playerTools.Slingshot) --> true

With that in mind, let’s create the code. I’ll assuming that there’s two BindableFunctions parented to the script—one for giving a tool and one for checking for a tool:

-- services:
local dataStoreService = game:GetService("DataStoreService")
local playersService = game:GetService("Players")

-- variables:
local playerToolsStore = dataStoreService:GetDataStore("PlayerTools")
local playerTools = {}


-- main:
playersService.PlayerAdded:Connect(function(player)
    -- get table.
    local userId = tostring(player.UserId)
    local isSuccessful, tools = pcall(playerToolsStore.GetAsync, playerToolsStore, userId)
    -- if request failed, kick player and return from function.
    if not isSuccessful then
        player:Kick("An error occurred while getting player tools.")
        return
    end
    if not tools then
        -- table doesn't exist? first time player, create table.
        tools = {}
        isSuccessful = pcall(playerToolsStore.SetAsync, playerToolsStore, userId, tools)
        -- if request failed, kick player and return from function.
        if not isSuccessful then
            player:Kick("An error occurred while creating player tools.")
            return
        end
    end
    -- add to playerTools dictionary for later.
    playerTools[player] = tools
end)

function script.HasTool.OnInvoke(player, toolName)
    local tools = playerTools[player]
    
    return tools and tools[toolName]
end

function script.GiveTool.OnInvoke(player, toolName)
    local tools = playerTools[player]
    if not tools then return false end
    tools[toolName] = true
    local isSuccessful = pcall(playerToolsStore.SetAsync, playerToolsStore, tostring(player.UserId), tools)
    if not isSuccessful then
        player:Kick("An error occurred while updating player tools.")
        return false
    end
    
    return true
end

I haven’t tested this code, so there may be a few issues. This code doesn’t handle request fails very well; it simply kicks the player, which will result in a bad user experience and even loss of purchases. You should treat this as just an example.

You can learn more about data stores here and here.

8 Likes

Thank you, but problem is that, I don’t use Bindable functions. I also use local scripts to process the shop process without checking with a server script as I am a new developer and not concerned with exploiting. So I need a script that saves the tool once the tool is in the player’s backpack. @Dandystan

You cannot access data stores from the client. As I’ve said, the code is just an example that demonstrates how you could go about doing this. You do not need to use BindableFunctions.

1 Like

It is a lot easier to learn best practices earlier than later - trust me.

As for your situation you actually have to transfer data to the server using a remote event somewhow. Data is saved on the server, so use a server script to do so.

The example above is good a good outline.

2 Likes

Thank you for the recommendation, could you link me to the page that teaches about game security?

Here’s an article talking about general game security
Here’s an article to help with the server-client model
Remote Functions/Events
And DataStoreService
And a helpful overview of datastores

All of these should be good resources for you.

2 Likes

Thank you!

No problem :smile:

Sorry to bump but where would this script go? Would it be a server script assigning a table to every new player that joins to avoid exploiting or a localscript somewhere starterplayer?