How to save a TextBox's Text

Gotcha. I did a little more work this morning and I found out that my DataStore Key looks like this
image
How would I go about loading and saving the actual string, instead of that whole table, since it looks like that’s what my error was above

Print the Data variable on the server right before you save it so we can see what it is. something tells me it’s not actually the notepad text

In the last few hours I’ve been trying to figure out how to use DataStores and get an actual understanding of them lol, and I’ve finally got a working script. :smiley: I changed your code around a bit, added stuff and removed stuff such as a SavedData table you had, and I added a RemoteEvent to send the Data over.

If you think I should edit some stuff or change some stuff let me know!

Client (some parts have been cut out, but this is the jest):

local NotepadData = ReplicatedStorage.Events.RemoteFunctions.NotepadData
local NotepadSetText = ReplicatedStorage.Events.RemoteEvents.NotepadSetText
local TextBox = script.Parent.TopbarUIs.Notes.Main.Container.TextBox

NotepadSetText.OnClientEvent:Connect(function(Data)
	if Data then
		TextBox.Text = Data
	end
end)

game.Players.PlayerRemoving:Connect(function(Player)
	local LocalPlayer = game.Players.LocalPlayer
	if Player.Name == LocalPlayer.Name then
		NotepadData:InvokeServer(true, TextBox.Text)
		print("(client) "..LocalPlayer.Name.." left, client invoked server to save data: "..TextBox.Text)
	end
end)
-- ^^ not to sure if this works yet. vv this below will change to 60s and not 10s

spawn(function()
	while wait(10) do
		NotepadData:InvokeServer(true, TextBox.Text)
		print("(client) AUTO SAVE, attempted to send over data to server from client: "..TextBox.Text)
	end
end)

Server:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local DataStoreService = game:GetService("DataStoreService")
local NotepadData = DataStoreService:GetDataStore("NotepadData")
local RemoteFunction = ReplicatedStorage.Events.RemoteFunctions.NotepadData
local RemoteEvent = ReplicatedStorage.Events.RemoteEvents.NotepadSetText
local SavedData = ""

Players.PlayerAdded:Connect(function(Player)
	local Success, Data = pcall(function()
		return NotepadData:GetAsync("User_"..Player.UserId)
	end)
	if Success then
		RemoteEvent:FireClient(Player, Data)
		print("(server) successfully fetched data. data fired to client via remote")
	end
end)

RemoteFunction.OnServerInvoke = function(Player, State, Data)
	if State == true then
		SavedData = Data
		local Success, Data = pcall(function()
			NotepadData:SetAsync("User_"..Player.UserId, Data)
		end)
		if Success then
			print("(server) SUCCESSFULLY SAVED DATA")
		end
	elseif State == false then
		print("(server) is sending over data to client")
		return SavedData
	end
end

I temporally (commented it out) removed this part to see if the game.Players.PlayerRemoving part would work and it didn’t. Do you or anyone else know how I would save the data when the player leaves?

Would you know how I could solve this or if anyone else could?

Don’t use the client PlayerRemoving thing. Do this:

I’ve thought about it but this fires way to many times
image

In the server’s RemoteFunction call, only fill in the SaveData table.

Not sure if you saw my recent script but I ended up removing the SaveData table. I’ve been seeing how I should save the data on the server so I came up with a decent method though it won’t save (text updates and loads the data saved though, the server script just does not save the text)

Client:

NotepadSetText.OnClientEvent:Connect(function(Data)
	if Data then
		TextBox.Text = Data
		if game.Workspace:FindFirstChild(LocalPlayer.Name) then
			game.Workspace[LocalPlayer.Name]:SetAttribute("NotepadData", Data)
		end
	end
end)

TextBox:GetPropertyChangedSignal("Text"):Connect(function()
	if game.Workspace:FindFirstChild(LocalPlayer.Name) then
		game.Workspace[LocalPlayer.Name]:SetAttribute("NotepadData", TextBox.Text)
	end
end)

Server:

game.Players.PlayerRemoving:Connect(function(Player)
	local Character = Player.Character or Player.CharacterAdded:Wait()
	local CharacterNotepadData = Character:GetAttribute("NotepadData")
	pcall(function()
		NotepadData:SetAsync(Player.UserId, CharacterNotepadData)
	end)
end)

If the server’s remote code is only setting an attribute, then the data store throttling from this post shouldn’t be happening.

Also, set the attribute on the player instance, not the character, since you don’t know if the character exists when the PlayerRemoving event fires.

Would you like me to show you an example of a very simple thing I made a while ago which follows the rules I posted about here?

Do you mean put the Attribute on game.Players.LocalPlayer? If so how would I access the attribute via a Server Script.

Sure!

Actually, I just realized something and I don’t know why I didn’t see it earlier: you’re setting the attribute on the client, and then trying to access it from the server. WRONG! The server will not see that change.

Anyway, read the code in this module. The way it’s used is to have a server script require the MainModule.

Change FOV Chat Command.rbxm (2.5 KB)

Oh, I can’t seem to have my data save when the player join’s I’ve tried so many meathods.

The scripts look so be pretty similar to the scripts you’ve gave me before!!

The way my thing works is that you input a command /fov 90 into the chat, and it will save that value between games.

Try to figure out the entire sequence of events from the time you type the message into chat to the time you rejoin. I think as a working example, rather than just bits and pieces of code samples, it could help you figure out the way to do this.

If you want to save other data in the future beyond just notepad data, there’s also a clever way to centralize all of it into 1 big table which is saved to data stores as well, and that makes it so doing this process much easier after the first time.

Thank you so much for the help, though I’ve only gotten back to square one, my data won’t save when the player leaves and It’s so frustrating now lol… I can’t tell what I’m doing wrong.

Full ServerScript:

local DataStoreService = game:GetService("DataStoreService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local NotepadData = DataStoreService:GetDataStore("NotepadData")
local NotepadDataRemoteFunction = ReplicatedStorage:WaitForChild("Events").RemoteFunctions.NotepadData
local NotepadSetTextRemoteEvent = ReplicatedStorage:WaitForChild("Events").RemoteEvents.NotepadSetText
local LoadedDataBindableEvent = Instance.new("BindableEvent")
local LoadedData = {}
local ServerData = ""

NotepadDataRemoteFunction.OnServerInvoke = function(Player, RequestType, DataToHandle)
	if RequestType == true then
		ServerData = DataToHandle
		pcall(function()
			NotepadData:SetAsync(Player.UserId, DataToHandle)
		end)
	elseif RequestType == false then
		return ServerData
	end
end

function PlayerJoined(Player)
	local Success, SavedData = pcall(function()
		return NotepadData:GetAsync(Player.UserId)
	end)
	if Success then
		ServerData = SavedData
		NotepadSetTextRemoteEvent:FireClient(Player, SavedData)
	end
	LoadedData = true
	LoadedDataBindableEvent:Fire()
end

function PlayerLeft(Player)
	local NewData = ServerData
	if NewData then
		ServerData = nil
		pcall(function()
			NotepadData:SetAsync(Player.UserId, NewData)
		end)
	end
end

Players.PlayerAdded:Connect(PlayerJoined)
Players.PlayerRemoving:Connect(PlayerLeft)

Full LocalScript:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local NotepadData = ReplicatedStorage.Events.RemoteFunctions.NotepadData
local NotepadSetText = ReplicatedStorage.Events.RemoteEvents.NotepadSetText
local TextBox = script.Parent.TopbarUIs.Notes.Main.Container.TextBox

NotepadSetText.OnClientEvent:Connect(function(SavedData)
	if SavedData then
		TextBox.Text = SavedData
	end
end)

spawn(function()
	while wait(300000) do --this number is this large so that way i can test if the player leave script works bc ik this autosave part works
		NotepadData:InvokeServer(true, TextBox.Text)
	end
end)

I really suggest you just copy my code and fit it almost exactly to your needs. You’re not saving data on a per-player basis in the server script, your server script’s remote function isn’t yielding for the loaded player data, that same function is doing database save calls (:SetAsync) every single time it’s called despite that only sensibly happening upon players leaving, and you don’t know when the client should request that the server save their data.

What you should do is play around with the thing I made. Experiment with different properties, maybe change the field of view functionality to instead edit some text in a GUI. Save your changes to a new test place on your profile and see if it saves in live games. If so, copy over your changes to your actual game.

I know this is a headache, and it seems so impossible the first time you try it. It’s unfortunate that saving data can be so difficult, but that’s just how it is on Roblox since the tools they give you are designed to be barebones for flexibility’s sake. Once you learn how to do this, however, it will be much easier in the future — especially if you decide to save more than once piece of data at once, since doing that is just a matter of converting the data to a dictionary.

At this point I think everything that future readers might need has already been said in this thread, so if you want more immediate help, add my Discord and I’ll be happy to continue: GFink#1089

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.