I need help with making this script work!

Ah, I see. In that case, you don’t need the second client script that I provided earlier.

To integrate the GUI into your game, you can place the TextBox object (that is displayed in the GUI) inside the GUI frame that you have created. You can then use the FocusLost event of the TextBox object to update the player’s attribute whenever the text changes.

Here’s an example:

-- Get references to player and TextBox objects
local player = game.Players.LocalPlayer
local textBox = script.Parent.TextBox

-- Update the TextBox text when the player first joins
local function onPlayerJoin()
    local text = player:GetAttribute("Text") or ""
    textBox.Text = text
end
onPlayerJoin()

-- Update the player's attribute whenever the text changes
textBox.FocusLost:Connect(function(enterPressed)
    if enterPressed then
        local text = textBox.Text
        player:SetAttribute("Text", text)
    end
end)

Make sure to place this script inside StarterPlayerScripts and name it “TextBox”.

I hope that helps!

ima just test the datastore hold on

Sure, take your time testing the DataStore. Let me know if you have any further questions or need any more assistance.

i will dw :)) (20 char be like lol) @CookieTechAi

No worries, feel free to reach out if you have any questions or concerns. Have a great day!

it made its own instead of updating my gui

I think I see what happened. Since the script is creating a new ScreenGui for each player, it won’t be able to find the existing ScreenGui that you created manually in the PlayerGui.

To fix this, you need to make sure that the script is using the existing ScreenGui and TextLabel objects instead of creating new ones. Here’s how you can modify the previous script to do that:

local MyDataStore = game:GetService("DataStoreService"):GetDataStore("MyDataStoreName")
local DEFAULT_TEXT = "Hello, world!" -- Change this to your default message

local function getScreenGui(player)
    local screenGui = player.PlayerGui:FindFirstChild("MyScreenGui")
    if not screenGui then
        screenGui = Instance.new("ScreenGui")
        screenGui.Name = "MyScreenGui"
        screenGui.Parent = player.PlayerGui
        
        local messageLabel = Instance.new("TextLabel")
        messageLabel.Name = "MessageLabel"
        messageLabel.Position = UDim2.new(0.5, 0, 0.5, 0)
        messageLabel.Size = UDim2.new(0, 200, 0, 50)
        messageLabel.AnchorPoint = Vector2.new(0.5, 0.5)
        messageLabel.BackgroundTransparency = 1
        messageLabel.Font = Enum.Font.SourceSans
        messageLabel.TextColor3 = Color3.new(1, 1, 1)
        messageLabel.TextSize = 20
        messageLabel.Parent = screenGui
    end
    
    return screenGui.MessageLabel
end

local function loadText(player)
    local success, value = pcall(function()
        return MyDataStore:GetAsync(tostring(player.UserId))
    end)

    if success then
        return value or DEFAULT_TEXT
    else
        warn("Failed to load text for player " .. player.Name .. ": " .. tostring(value))
        return DEFAULT_TEXT
    end
end

local function saveText(player, newText)
    local success, value = pcall(function()
        MyDataStore:SetAsync(tostring(player.UserId), newText)
    end)

    if not success then
        warn("Failed to save text for player " .. player.Name .. ": " .. tostring(value))
    end
end

local players = game:GetService("Players")

players.PlayerAdded:Connect(function(player)
    local messageLabel = getScreenGui(player)
    
    local newText = loadText(player)
    messageLabel.Text = newText

    player.Chatted:Connect(function(message)
        if string.sub(message, 1, 11) == "-changetext" then
            newText = string.sub(message, 13)
            messageLabel.Text = newText
            saveText(player, newText)
        end
    end)
end)

players.PlayerRemoving:Connect(function(player)
    saveText(player, player.PlayerGui.MyScreenGui.MessageLabel.Text)
end)

Here, instead of creating a new ScreenGui and TextLabel objects each time, the getScreenGui function checks if the ScreenGui already exists and creates it only if necessary. Then, it returns the existing MessageLabel object that corresponds to that ScreenGui.

ill let u kknow if this works wish me luck pls

Of course, good luck! Don’t hesitate to ask if you have more questions or issues.

how to make it so my the default text is two lines

You can make the default text two lines by adding a new line character \n between the two lines of text. Here’s an example:

local DEFAULT_TEXT = "Hello,\nworld!"

This will display the default text as two lines:

Hello,
world!

You can adjust the position and size of the TextLabel accordingly to ensure that both lines are visible.

ty let me try this one

You’re welcome, let me know if you need any further assistance!

its not saving the text when no players are in server and you rejoin

The script should save the text to the DataStore when the player leaves the game, so that it can be loaded the next time the player rejoins. However, if you’re still encountering issues where the text is not saved across server shutdowns, it may be because of how Roblox handles game shutdowns.

When a Roblox game shuts down, it doesn’t always call the “PlayerRemoving” event for each player before shutting down. This means that if the server shuts down abruptly, the script may not have a chance to save the player data to the DataStore. To mitigate against this, you can use the game:BindToClose() function to make sure your script has a chance to save the data before the server shuts down.

Here’s an updated version of the script that uses game:BindToClose() to handle server shutdowns:

local DataStoreService = game:GetService("DataStoreService")
local MyDataStore = DataStoreService:GetDataStore("MyDataStoreName")
local DEFAULT_TEXT = "Hello,\nworld!"

local function getScreenGui(player)
    local screenGui = player.PlayerGui:FindFirstChild("MyScreenGui")
    if not screenGui then
        screenGui = Instance.new("ScreenGui")
        screenGui.Name = "MyScreenGui"
        screenGui.Parent = player.PlayerGui
        
        local messageLabel = Instance.new("TextLabel")
        messageLabel.Name = "MessageLabel"
        messageLabel.Position = UDim2.new(0.5, 0, 0.5, 0)
        messageLabel.Size = UDim2.new(0, 200, 0, 50)
        messageLabel.AnchorPoint = Vector2.new(0.5, 0.5)
        messageLabel.BackgroundTransparency = 1
        messageLabel.Font = Enum.Font.SourceSans
        messageLabel.TextColor3 = Color3.new(1, 1, 1)
        messageLabel.TextSize = 20
        messageLabel.TextWrapped = true -- Allow text to wrap to multiple lines
        messageLabel.Parent = screenGui
    end
    
    return screenGui.MessageLabel
end

local function loadText(player)
    local success, value = pcall(function()
        return MyDataStore:GetAsync(tostring(player.UserId))
    end)

    if success then
        return value or DEFAULT_TEXT
    else
        warn("Failed to load text for player " .. player.Name .. ": " .. tostring(value))
        return DEFAULT_TEXT
    end
end

local function saveText(player, newText)
    local success, value = pcall(function()
        MyDataStore:SetAsync(tostring(player.UserId), newText)
    end)

    if not success then
        warn("Failed to save text for player " .. player.Name .. ": " .. tostring(value))
    end
end

local function saveAllPlayersData()
    for _, player in ipairs(game.Players:GetPlayers()) do
        saveText(player, player.PlayerGui.MyScreenGui.MessageLabel.Text)
    end
end

local players = game:GetService("Players")

players.PlayerAdded:Connect(function(player)
    local messageLabel = getScreenGui(player)
    
    local newText = loadText(player)
    messageLabel.Text = newText

    player.Chatted:Connect(function(message)
        if string.sub(message, 1, 11) == "-changetext" then
            newText = string.sub(message, 13)
            messageLabel.Text = newText
            saveText(player, newText)
        end
    end)
end)

players.PlayerRemoving:Connect(function(player)
    saveText(player, player.PlayerGui.MyScreenGui.MessageLabel.Text)
end)

game:BindToClose(function()
    saveAllPlayersData()
end)

This version of the script adds a new function saveAllPlayersData() that saves the data for all players in the game. It also uses the game:BindToClose() function to call saveAllPlayersData() before the server shuts down.

This should ensure that the data is saved to the DataStore even if the server shuts down abruptly.

Its not indiiviuial guis its one whole gui

I apologize for the confusion. In that case, you can modify the same loadText and saveText functions to load and save the entire ScreenGui and its children instead of just the MessageLabel.

Here’s how you can modify those functions:

local function loadScreenGui(player)
    local success, value = pcall(function()
         return MyDataStore:GetAsync(tostring(player.UserId))
    end)

    if not success then
        warn("Failed to load Text for player " .. player.Name .. ": " .. tostring(value))
        return nil
    end

    return value
end

local function saveScreenGui(player, screenGuiData)
    local success, value = pcall(function()
        MyDataStore:SetAsync(tostring(player.UserId), screenGuiData)
    end)

    if not success then
        warn("Failed to save Text for player " .. player.Name .. ": " .. tostring(value))
    end
end

Now, loadScreenGui will return the entire ScreenGui and its children as a single object, and saveScreenGui will save the entire ScreenGui object.

However, since the TextLabel inside your ScreenGui is named “TextLabel”, you still need to adjust the code to ensure that the correct TextLabel is being updated when a player’s text is changed. Here’s an updated version of the players.PlayerAdded event to make sure the correct TextLabel is being updated:

players.PlayerAdded:Connect(function(player)
    local screenGui = player.PlayerGui:FindFirstChild("MyScreenGui")
    if not screenGui then
        screenGui = Instance.new("ScreenGui")
        screenGui.Name = "MyScreenGui"
        screenGui.Parent = player.PlayerGui
        
        local messageLabel = Instance.new("TextLabel")
        messageLabel.Name = "TextLabel"
        messageLabel.Position = UDim2.new(0.5, 0, 0.5, 0)
        messageLabel.Size = UDim2.new(0, 200, 0, 50)
        messageLabel.AnchorPoint = Vector2.new(0.5, 0.5)
        messageLabel.BackgroundTransparency = 1
        messageLabel.Font = Enum.Font.SourceSans
        messageLabel.TextColor3 = Color3.new(1, 1, 1)
        messageLabel.TextSize = 20
        messageLabel.TextWrapped = true -- Allow text to wrap to multiple lines
        messageLabel.Parent = screenGui
    end

    local screenGuiData = loadScreenGui(player)
    if screenGuiData then
        screenGui:ClearAllChildren()
        for _, childData in ipairs(screenGuiData:GetChildren()) do
            local child = Instance.new(childData.ClassName)
            for property, value in pairs(childData:GetProperties()) do
                if property ~= "Parent" then
                    child[property] = value
                end
            end
            child.Parent = screenGui
        end
    end

    player.Chatted:Connect(function(message)
        if string.sub(message, 1, 11) == "-changetext" then
            local newText = string.sub(message, 13)
            screenGui.TextLabel.Text = newText
            saveScreenGui(player, screenGui)
        end
    end)
end)

This version of the players.PlayerAdded event will now get the existing ScreenGui for the player and load the data for that ScreenGui using loadScreenGui. It will then clear all of the children of the ScreenGui and recreate them using the data that was loaded.

Finally, it will make sure to update the correct TextLabel object when a player’s text is changed.

but i dont want it to create a screen gui and text label cuz i have one

I see. In that case, you can modify the loadScreenGui and saveScreenGui functions to save and load only the Text property of your existing TextLabel within the ScreenGui.

Here’s how you can modify those functions:

local function loadText(player)
    local success, value = pcall(function()
        return MyDataStore:GetAsync(tostring(player.UserId))
    end)

    if success then
        return value or DEFAULT_TEXT
    else
        warn("Failed to load text for player " .. player.Name .. ": " .. tostring(value))
        return DEFAULT_TEXT
    end
end

local function saveText(player, newText)
    local success, value = pcall(function()
        MyDataStore:SetAsync(tostring(player.UserId), newText)
    end)

    if not success then
        warn("Failed to save text for player " .. player.Name .. ": " .. tostring(value))
    end
end

Now, loadText will load only the saved text from the DataStore and saveText will save only the updated text to the DataStore.

With these updated functions, you no longer need the players.PlayerAdded event to create the ScreenGui and TextLabel. Instead, you can set the default text of your existing TextLabel using the result of loadText.

local DEFAULT_TEXT = "Hello,\nworld!"
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local MyDataStore = DataStoreService:GetDataStore("MyDataStore")

local textLabel = script.Parent.TextLabel -- Change "TextLabel" to the name of your existing TextLabel

function onPlayerJoined(player)
    local savedText = loadText(player)

    textLabel.Text = savedText

    player.Chatted:Connect(function(message)
        if string.sub(message, 1, 11) == "-changename" then
            local newName = string.sub(message, 13)
            player.Name = newName
        elseif string.sub(message, 1, 11) == "-changetext" then
            local newText = string.sub(message, 13)
            textLabel.Text = newText
            saveText(player, newText)
        end
    end)

    player.CharacterAdded:Connect(function()
        textLabel.Text = savedText
    end)

    player:LoadCharacter()
end

function onPlayerLeaving(player)
    saveText(player, textLabel.Text)
end

Players.PlayerAdded:Connect(onPlayerJoined)
Players.PlayerRemoving:Connect(onPlayerLeaving)

This updated script should allow you to use your existing ScreenGui and TextLabel while still saving and loading the text using the DataStore.

i dont want it to set back to default on rejoin i want it to put updated on rejoin