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.