#Datastore saving backpack issue

1 messages · Page 1 of 1 (latest)

bright pawn
#

Since I could only access character via using player parameter, the character tools will not save as the player has already remove. Which means if I am holding the tool while I leave the game it will not save. What should I do?

#

`local datastore = game:GetService("DataStoreService")
local dataname = datastore:GetDataStore("BackpackData")
local serverstorage = game:GetService("ServerStorage").Tools

game.Players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Wait()
local backpack = plr:WaitForChild("Backpack")
local plrdata = plr.UserId

local success, currenttools = pcall(function()
    return dataname:GetAsync(plr.UserId)
end)

if success and currenttools then
    for _, tool in pairs(currenttools) do
        if serverstorage:FindFirstChild(tool) then
            serverstorage[tool]:Clone().Parent = backpack
        end
    end
end

end)

game.Players.PlayerRemoving:Connect(function(plr)
local tools = {}
local backpack = plr:WaitForChild("Backpack")
local plrdata = plr.UserId

for _, v in pairs(backpack:GetChildren()) do
    if v:IsA("Tool") then
        table.insert(tools, v.Name)
    end
end

for _, v in pairs(plr.Character:GetChildren()) do
    if v:IsA("Tool") then
        table.insert(tools, v.Name)
    end
end

local success, err = pcall(function()
    dataname:SetAsync(plr.UserId, tools)
end)
if not success then
    warn("error"..err)
end

end)
`

acoustic coral
#

there's thousands of ways to do it so pick one

bright pawn
acoustic coral
#

there's thousands of ways and that is one of them

bright pawn
acoustic coral
#

well you could do it from within every tool, or you could do character.childadded/removed, or you could make your own backpack system and track it that way, or you could do it from a script that reads every tool and connects to their ancestrychanged or tool.equip/unequip, or you could hold all tools in memory so they dont get deleted when the player leaves regardless of where they are. there's more but these are probably the most obvious.

acoustic coral
bright pawn
acoustic coral
#

very, very rarely is there a one definitive correct answer

bright pawn
#

yeah but ive never thought there is many ways to format this

quiet slate
#

Just keep a list of all the tools that the player has and save/load based on it.

#

Or be lazy and fetch every tool the player has in both their character and backpack.

bright pawn
#

but it doesnt work

quiet slate
#

then choose another solution.

bright pawn
#

most annoying part is you can only access characterremove after you write playerremoved

#

which makes it useless

#

@acoustic coral if there is alot of way to fix this, what is the most ideal way in your opinion?

acoustic coral
#

whichever suits your game the best

bright pawn
#

i mean i am not making a game, it is just practising

acoustic coral
#

then practice making all of them

bright pawn
#

but which method is the most common method

#

that is the only thing I wanted to know

acoustic coral
#

all of them

bright pawn
#

ok let's say this, if you were me which one you gonna use?

#

you cant just use all of them

acoustic coral
#

i'd make all of them and figure out the difference between each one and decide for myself which one i'd want to use when i want to use them later on

bright pawn
#

which one is the simpliest way

acoustic coral
#

you can't decide for yourself if you don't know the pros and cons of each solution

#

eh they're all about the same difficulty. making your own backpack is probably hardest tho

bright pawn
#

like striaght foward

#

and easy to understand

acoustic coral
#

yea you're gonna have to get used to the fact that there is no straight forward easy answers.

bright pawn
#

i mean in comparison to all methods

#

there is 100% a way that is simple

#

if there is alot of methods

acoustic coral
#

and that one method changes on what you're trying to do

#

you're also talking as if i haven't made all of them myself, i have.

bright pawn
#

just a simple backpack saving

acoustic coral
#

not asking you to do something i wouldn't do myself.

#

and you said you wanted practice ey - pick one at random and go with that.

bright pawn
bright pawn
acoustic coral
#

you can spend the next week deciding which one to use based on other people's opinions, or you can spend the same time making each one and get to the same answer

undone tendon
#

Just give the man his answer stop being so egotistical holy

modest sandalBOT
#

studio** You are now Level 1! **studio

bright pawn
#

I just wanted to learn 😅

acoustic coral
undone tendon
#

Literally

acoustic coral
#

i'll let you take it from here salute

undone tendon
#

Jesus man

bright pawn
#

i reckon there is a way that isnt clumsy and doable in a single script

#

i am practising as organised as possible as well

undone tendon
#

You use OOP coding?

bright pawn
undone tendon
#

Got a player class?

bright pawn
#

what is a player class😭

undone tendon
#

A player object

#

Using object orientated programming

undone tendon
#

Make a player class and a player service, log player joins, create a player class when they join

#

Then, inside the class set an inventory class

#

And log every tool in the inventory class

#

That is how i would do it

bright pawn
#

i successfully saves the player backpack, but not when the player equiped the tool which brings the tool into a children of the character's

#

like when i hold the tool, i rejoin it wont save

#

this is the issue I am facing rn

undone tendon
#

Let me look at your script rq

bright pawn
#

alright

undone tendon
#

Oh youre accessing the character when the player has already left

#

I think a better approach would be

bright pawn
#

yeah lol

#

i couldnt find a way to access the character since the player already left

undone tendon
#

Yeah the thing is you cant

bright pawn
#

ik 😭

undone tendon
#

So the best solution is probably to just

#

Hold a table with every table,

#

Player*

#

And have their tools there and it updates whenever a tool is added to their character

#

Then access that table on player leave

#

Honestly id say using a player object would simplify it by like,

#

99999%

undone tendon
#

😂

#

How long have you been coding ?

bright pawn
#

a month lol

undone tendon
#

Oh I see thats good progress

bright pawn
#

thanks man

undone tendon
#

Do you know about services?

bright pawn
#

ya

#

tweens

#

runservice

#

pathfinding?

undone tendon
#

No i mean like

modest sandalBOT
#

studio** You are now Level 2! **studio

undone tendon
#

Services

#

Like

#

Services vs Controllers

#

Modulescript Services 😅

bright pawn
#

ahh

#

module scripts

#

the purple thingy?

undone tendon
#

LOL yes those

bright pawn
#

oh yea

undone tendon
#

Have you heard of Knit?

bright pawn
#

no lol

#

sounds familiar

undone tendon
#

Id really recommend dabbling in Knit using Services/Controllers and using OOP classes

#

But for now,

#

Ok so do this

#

At the top of your code define a table something like

#

local playerTools = {}

bright pawn
#

yep

undone tendon
#

So now you have a table that will hold all the tools right

#

So now when you add a player you do player.PlayerAdded:Connect(function(player)) and inside it do

#

playerTools[player.UserId] = {}

bright pawn
#

like this

undone tendon
#

So now your table holds a reference to the player and sets up a table for it

#

Yessir!

#

Do plr lol

bright pawn
#

oh so the table saves the userid

bright pawn
undone tendon
#

Since the variable you set was (plr)

#

So now you have a table defined

bright pawn
#

yep

undone tendon
#

Now you wanna save the tools they get right

#

You have the tools in replicated storage?

bright pawn
#

in serverstorage inside a folder

undone tendon
#

Alr alr

#

So now you know how to get the tools of a player?

bright pawn
#

in the backpack or the character

undone tendon
#

so whenever a tool is added

#

Add it to the table

#

At Player.UserId

#

So like for example

bright pawn
#

wait isnt local playerTools = {}
is a table for a list of userid?

#

since it is playerTools[plr.UserId] = {}

undone tendon
#

Its a table that holds UserId's, that holds tables

#

Its a table inside a table

#

So it looks like this

bright pawn
#

is this like metatable or smth, correct me if im wrong xd

undone tendon
#

playerTools = {
[UserId] = {"sword","shield"},
[AnotherUserId = {"sword"},
[UrUserId] = {"hammer"},
}

#

It looks like that

undone tendon
undone tendon
#

So basically you have a table holding userId's, that holds a table that has their tools!

#

So now you can do,

#

character.ChildAdded:Connect(function(child))

#

And then you can check if its a tool,

coral quarry
#

Bro your post has 150 replies mine dont even have one

undone tendon
#

LOL

undone tendon
#

Im teaching 🙏🏽

#

Then you do,

#

If child:IsA("tool") then

#

playerTools[player.UserId] = child

#

Boom!

bright pawn
#

where do i put character.ChildAdded:Connect(function(child))

undone tendon
#

On player added

bright pawn
#

liek i have to crete a character

undone tendon
#

So right after player added inside

#

Do player.CharacterAdded

#

It should autofill

bright pawn
#

oh

undone tendon
#

Lmk when you got it

#

Ill review it 🙏🏽

bright pawn
#

okok let me digest it rq

coral quarry
undone tendon
#

Oh yeah for sure

#

Im not very good but i can try 😅

bright pawn
#

like this?

undone tendon
#

oh close

modest sandalBOT
#

studio** You are now Level 3! **studio

undone tendon
#

its plr.CharacterAdded:Connect character and thenn character.ChildAdded!

#

You wanna check what gets added inside the "character" 😁

#

imma send an example

bright pawn
modest sandalBOT
#

studio** You are now Level 9! **studio

bright pawn
#

lol is it like this

undone tendon
#

heck yeah now you do one for the backpack

#

but you wanna make sure the child doesnt already excist

bright pawn
#

wait so what did i just did evilcat

undone tendon
#

ok wait

#

you wanna check the backpack instead actually

#

so when a child is added to the backpack, add it to the table

#

ok wait hold

bright pawn
#

this is the whole script tn

#

rn

undone tendon
#

i totally forgot its a table

bright pawn
#

lol

undone tendon
#

ok let me send an example hold

bright pawn
#

alr alr

undone tendon
#

OK

#

here we go

#

you have to use table.insert not playerTools[player.UserId] since itd overwrite the table with the child woopsies

#

ok so basically that saves all the tools to the playerTools table

#

WAIT.

#

important question

#

are you storing like, multiple instances of the same tool

bright pawn
undone tendon
#

like what are you putting in the inventories

bright pawn
#

oh

#

i got some cloned tools

#

same tools

#

the most frustrating problem all along is I am unable to save the tool if the player is holding the tool, since it got removed from the player's backpack. Otherwise every single tool in the backpack when i leave remains when i rejoin lol

undone tendon
#

yeah lol i get that

#

i struggled with saving tools for my grow a garden clone game with scaling tools

#

that shit took me so long to figure out 🤣

bright pawn
#

lmao

undone tendon
#

lowkey just copy this honestly

#

local Players = game:GetService("Players")

local playerTools = {}

local function addTool(player, tool)
local tools = playerTools[player.UserId]
-- Avoid duplicates
for _, t in ipairs(tools) do
if t == tool then return end
end
table.insert(tools, tool)
end

local function removeTool(player, tool)
local tools = playerTools[player.UserId]
for i = #tools, 1, -1 do
if tools[i] == tool then
table.remove(tools, i)
break
end
end
end

local function trackTools(player)
playerTools[player.UserId] = {}

local function onToolAdded(tool)
    if tool:IsA("Tool") then
        addTool(player, tool)
        -- Connect to removal to keep table accurate
        tool.AncestryChanged:Connect(function(child, parent)
            if not parent then
                removeTool(player, tool)
            end
        end)
    end
end

local backpack = player:WaitForChild("Backpack")
backpack.ChildAdded:Connect(onToolAdded)
backpack:GetChildren() -- in case tools already there
for _, tool in ipairs(backpack:GetChildren()) do
    onToolAdded(tool)
end

local function onCharacterAdded(character)
    character.ChildAdded:Connect(onToolAdded)
    for _, tool in ipairs(character:GetChildren()) do
        onToolAdded(tool)
    end
end

if player.Character then
    onCharacterAdded(player.Character)
end
player.CharacterAdded:Connect(onCharacterAdded)

end

Players.PlayerAdded:Connect(trackTools)

#

this entire thing keeps track of tools

#

then when you need to access them just do local tools = playerTools[player.UserId]

#

and then do for _, tool in ipairs(playerTools[player.UserId] do functionystuff end

bright pawn
#

this saves the tool?

undone tendon
#

ok hi

#

local Players = game:GetService("Players")

local playerTools = {}

local function addTool(player, tool)
local tools = playerTools[player.UserId]
if not tools then return end
-- Avoid duplicates
for _, t in ipairs(tools) do
if t == tool then return end
end
table.insert(tools, tool)
end

local function removeTool(player, tool)
local tools = playerTools[player.UserId]
if not tools then return end
for i = #tools, 1, -1 do
if tools[i] == tool then
table.remove(tools, i)
break
end
end
end

local function trackTools(player)
playerTools[player.UserId] = {}

local function onToolAdded(tool)
    if tool:IsA("Tool") then
        addTool(player, tool)
        tool.AncestryChanged:Connect(function(_, parent)
            if not parent then
                removeTool(player, tool)
            end
        end)
    end
end

local backpack = player:WaitForChild("Backpack")
backpack.ChildAdded:Connect(onToolAdded)
for _, tool in ipairs(backpack:GetChildren()) do
    onToolAdded(tool)
end

local function onCharacterAdded(character)
    character.ChildAdded:Connect(onToolAdded)
    for _, tool in ipairs(character:GetChildren()) do
        onToolAdded(tool)
    end
end

if player.Character then
    onCharacterAdded(player.Character)
end
player.CharacterAdded:Connect(onCharacterAdded)

end

Players.PlayerAdded:Connect(trackTools)

Players.PlayerRemoving:Connect(function(player)
print("PlayerRemoving for", player.Name)
local tools = playerTools[player.UserId]
if tools then
print("Tools count:", #tools)
for i, tool in ipairs(tools) do
-- do thing save to datastore
end
playerTools[player.UserId] = nil -- cleanup
else
print("No tools tracked for this player")
end
end)

bright pawn
#

how it is gonna save without data store servicehmm

undone tendon
#

what do you mean hmm

modest sandalBOT
#

studio** You are now Level 4! **studio

undone tendon
#

you add it hmm

bright pawn
#

wait

#

my mind is exploding

undone tendon
#

AHHHHHHHHHHHHHHHH

#

🧨

bright pawn
#

🤯

undone tendon
#

ok lowkey i think i just made this a lot more complicated than needs be

bright pawn
#

frfr

#

one small character thing turns to a mayday

undone tendon
#

OK

#

i got a bare bones version with absolutely no safety made!

#

local Players = game:GetService("Players")

local playerTools = {}

Players.PlayerAdded:Connect(function(player)
playerTools[player.UserId] = {}
player.CharacterAdded:Connect(function(character)
local backpack = player:WaitForChild("Backpack")
for _, child in pairs(backpack:GetChildren()) do
if child:IsA("Tool") then
print("CHILD ADDED")
table.insert(playerTools[player.UserId], child)
end
end

    for _, child in pairs(character:GetChildren()) do
        if child:IsA("Tool") then
            print("CHILD ADDED")
            table.insert(playerTools[player.UserId], child)
        end
    end

    backpack.ChildAdded:Connect(function(child)
        if child:IsA("Tool") then
            print("CHILD ADDED")
            table.insert(playerTools[player.UserId], child)
        end
    end)
    character.ChildAdded:Connect(function(child)
        if child:IsA("Tool") then
            print("CHILD ADDED")
            table.insert(playerTools[player.UserId], child)
        end
    end)
end)

end)

Players.PlayerRemoving:Connect(function(player)
local tools = playerTools[player.UserId]
if tools then
for _, tool in ipairs(tools) do
print(tool.Name)
end
playerTools[player.UserId] = nil
end
end)

#

literally all this does is logs what tools the player has

#

so keep your script as it was

#

but this would be the playerAdded script

#

and then when the player removes,

#

the tools will be inside playerTools[player.UserId]

#

oops forgot 1 safety

bright pawn
#

when i recieve the tools, it printed child added and when i leave it printed the tool name

undone tendon
#

local Players = game:GetService("Players")

local playerTools = {}

local function toolAlreadyTracked(tools, tool)
for _, t in ipairs(tools) do
if t == tool then
return true
end
end
return false
end

Players.PlayerAdded:Connect(function(player)
playerTools[player.UserId] = {}

player.CharacterAdded:Connect(function(character)
    local backpack = player:WaitForChild("Backpack")

    for _, child in pairs(backpack:GetChildren()) do
        if child:IsA("Tool") and not toolAlreadyTracked(playerTools[player.UserId], child) then
            print("TOOL ADDED")
            table.insert(playerTools[player.UserId], child)
        end
    end

    for _, child in pairs(character:GetChildren()) do
        if child:IsA("Tool") and not toolAlreadyTracked(playerTools[player.UserId], child) then
            print("TOOL ADDED")
            table.insert(playerTools[player.UserId], child)
        end
    end

    backpack.ChildAdded:Connect(function(child)
        if child:IsA("Tool") and not toolAlreadyTracked(playerTools[player.UserId], child) then
            print("TOOL ADDED")
            table.insert(playerTools[player.UserId], child)
        end
    end)

    character.ChildAdded:Connect(function(child)
        if child:IsA("Tool") and not toolAlreadyTracked(playerTools[player.UserId], child) then
            print("TOOL ADDED")
            table.insert(playerTools[player.UserId], child)
        end
    end)
end)

end)

Players.PlayerRemoving:Connect(function(player)
local tools = playerTools[player.UserId]
if tools then
for _, tool in ipairs(tools) do
--TODO
--DO SOMETHING WITH DATA STORE HERE EX SAVING
end
playerTools[player.UserId] = nil
end
end)

bright pawn
#

it got 1 extra tool when i hold the tool

undone tendon
#

yeah i forgot to make sure the child doesnt already exists

#

so what you have to do for tracking tools is constantly check

bright pawn
#

yep

undone tendon
#
  1. scan through backpack / character first
#

then 2. listen for new children added / when the tool is destroyed

#

so actually your script becomes this long now!

bright pawn
#

oh zamn

undone tendon
#

yep

#

gotta account for

#

everything

#

where it says TODO save tools to data store save the tools there

bright pawn
#

yep alr

undone tendon
#

basically just do everything you were already doing

bright pawn
#

how about when player is added

undone tendon
#

but use that to keep track of the tools, and save them on player leave

undone tendon
bright pawn
#

like when they join

#

i need to getasync

undone tendon
#

yeah just do exactly what you were doing

bright pawn
#

alr

undone tendon
#

but use that seperately to

#

save the tools in a table

#

and then use the table on player leave

bright pawn
#

ok ill try

bright pawn
undone tendon
#

sadly not

#

wait how did you save it before

#

did you save each individual tool by doing

#

data:SetAsync(player, tool)

#

before

#

im not gonna lie i have never dabbled in DataStore but i have dabbled in everything else

#

ok wait nvm i got it

#

so player.UserId, then playerTools[player.UserId]

bright pawn
#

this makes sense but confusing at the same time 😭

undone tendon
#

ok im gonna dm you hold on

bright pawn
#

alr

undone tendon
#

accept my friend request