Search code examples
luaroblox

How can I save the state of visibility of a Image Label?


I am developing a game and i need help storing the state of visibility of a ImageLabel

The state of visibility is false, and it becomes true when a specific tool interacts with a TextButton, but when I leave the game The ImageLabel won't be visible again and the tool is back on the inventory.

Can someone tell me how to store it

Btw sorry for bad english actually isn't my first language

Here's the TextButton code if interested:

script.Parent.MouseButton1Click:Connect(function()
    
    local ToolName = "Tool"
    local player = game.Players.LocalPlayer
    local Tool = player.Backpack:FindFirstChild(ToolName)
    Tool:Destroy()
    script.Parent.Parent.ImageLabel.Visible = true
    game.ReplicatedStorage.RemoveToolFromPlayer:FireServer(player)
end) 

Solution

  • In order to save data, you need create a DataStore. Please make sure you follow the instructions in the article to ensure that you've enabled DataStores in your game.

    So the flow of your data should be like this :

    1. When a player joins the game, use a Script to ask the DataStore if we have any information about this player. If not, create it. This information will be used to know whether they should have the tool, and if they can see the image.
    2. Send the data to the player using a RemoteEvent or have the player fetch it with a RemoteFunction.
    3. Have a LocalScript use that data to decide whether to show the ImageLabel, and whether the tools needs to be available.
    4. When the player uses the tool to reveal the image, use a RemoteEvent to tell the server that the stored data needs to be updated.
    5. When the player leaves (or every couple minutes), tell the DataStore to save the player's data.

    So, first you need to create a few objects to make this work :

    • a RemoteFunction in ReplicatedStorage named FetchPlayerData, this will allow the player to request the data from the server.
    • a RemoteEvent in ReplicatedStorage named RemoveToolFromPlayer, this will be used to update the player information, and remove the tool from the player's backpack.
    • a Script in ServerScriptService
    • a LocalScript as the child of your TextButton

    So in the Script :

    local DataStoreService = game:GetService("DataStoreService")
    local HttpService = game:GetService("HttpService")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local Players = game:GetService("Players")
    
    local PlayerDataStore = DataStoreService:GetDataStore("PlayerData")
    
    local FetchPlayerData = ReplicatedStorage.FetchPlayerData
    local RemoveToolFromPlayer = ReplicatedStorage.RemoveToolFromPlayer
    
    local playerData = {} -- map<playerName, table of data>
    local DEFAULT_PLAYER_DATA = {
        dataLoaded = false,
        hasTool = true,
        canSeeImage = false,
    }
    
    -- listen for when players join the game
    Players.PlayerAdded:Connect(function(player)
        playerData[player.Name] = DEFAULT_PLAYER_DATA
    
        -- fetch the information about the player from the data store
        local success, result = pcall(function()
            local dataString = PlayerDataStore:GetAsync(tostring(player.UserId))
            return HttpService:JSONDecode(dataString)
        end)
    
        if success and result ~= nil then
            playerData[player.Name] = result
        end
        playerData[player.Name].dataLoaded = true
    end)
    
    -- listen for when a player leaves the game
    Players.PlayerRemoving:Connect(function(player)
        -- update the data store with the player's information
        local success, result = pcall(function()
            local dataString = HttpService:JSONEncode(playerData[player.Name])
            PlayerDataStore:SetAsync(tostring(player.UserId), dataString)
        end)
        
        -- clear out the data
        playerData[player.Name] = nil
    end)
    
    -- listen for when the player uses the Tool
    RemoveToolFromPlayer.OnServerEvent:Connect(function(player)
        local data = playerData[player.Name]
        if data ~= nil then
            -- update the player's data
            data.hasTool = false
            data.canSeeImage = true
    
            -- remove the tool from their Backpack
            local TOOL_NAME = "Tool"
            local tool = player.Backpack:FindFirstChild(TOOL_NAME)
            if tool then
                tool:Destroy()
            end
        end
    end)
    
    -- listen for when the player requests their information
    FetchPlayerData.OnServerInvoke = function(player)
        return playerData[player.Name]
    end
    

    Then in your LocalScript :

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local Players = game:GetService("Players")
    
    local FetchPlayerData = ReplicatedStorage.FetchPlayerData
    local RemoveToolFromPlayer = ReplicatedStorage.RemoveToolFromPlayer
    local player = Players.LocalPlayer
    
    local Button = script.Parent
    local Image = script.Parent.Parent.ImageLabel
    
    -- ask the server about our data, and wait if it's not ready
    local playerData = {}
    local dataLoaded = false
    while not dataLoaded do
        playerData = FetchPlayerData:InvokeServer()
        dataLoaded = playerData.dataLoaded
    
        if not dataLoaded then
            wait(1)
        end
    end
    
    -- use the data to decide whether to show the image
    Image.Visible = playerData.canSeeImage
    
    -- listen for when the player interacts with the button
    Button.MouseButton1Click:Connect(function()
        local ToolName = "Tool"
        local Tool = player.Backpack:FindFirstChild(ToolName)
        if Tool then
            Image.Visible = true
            RemoveToolFromPlayer:FireServer()
        end
    end)
    

    I'll leave out the logic of getting the Tool, as it really wasn't part of your original question. But you can use similar logic to check whether to give the player the tool.