Devlog Help 1 - Saving String Values

Hello scripters.! This is my first devlog of me trying to create a developer game.


MY ISSUE:

When the value of the leaderstats change, they don’t save, they just return to “No”.


WHAT I WANT TO HAPPEN:

When the leaderstats change I want them to save in the leaderstats.


MY CURRENT SCRIPT:

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local DataStore = DataStoreService:GetDataStore("YourGameName")

-- Function to load player data
local function loadPlayerData(player)
	local key = "Player_" .. player.UserId

	local success, data = pcall(function()
		return DataStore:GetAsync(key)
	end)

	if success then
		return data
	else
		warn("Failed to load data for player " .. player.Name)
		return nil
	end
end

-- Function to save player data
local function savePlayerData(player, data)
	local key = "Player_" .. player.UserId

	local success, errorMessage = pcall(function()
		DataStore:SetAsync(key, data)
	end)

	if not success then
		warn("Failed to save data for player " .. player.Name .. ": " .. errorMessage)
	end
end

-- Create leaderstats and set initial values
local function setupLeaderstats(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"

	local forHire = Instance.new("StringValue")
	forHire.Name = "ForHire"
	forHire.Value = "No"
	forHire.Parent = leaderstats

	local hiring = Instance.new("StringValue")
	hiring.Name = "Hiring"
	hiring.Value = "No"
	hiring.Parent = leaderstats

	local posting = Instance.new("StringValue")
	posting.Name = "Posting"
	posting.Value = "No"
	posting.Parent = leaderstats

	local public = Instance.new("StringValue")
	public.Name = "Public"
	public.Value = "No"
	public.Parent = leaderstats

	leaderstats.Parent = player
end

-- Connect the function to player added event
Players.PlayerAdded:Connect(function(player)
	local playerData = loadPlayerData(player)

	if not playerData then
		setupLeaderstats(player)
	else
		-- Set values from loaded data
		player.leaderstats.ForHire.Value = playerData.ForHire
		player.leaderstats.Hiring.Value = playerData.Hiring
		player.leaderstats.Posting.Value = playerData.Posting
		player.leaderstats.Public.Value = playerData.Public
	end
end)

-- Connect the function to player removing event to save data
Players.PlayerRemoving:Connect(function(player)
	local playerData = {
		ForHire = player.leaderstats.ForHire.Value,
		Hiring = player.leaderstats.Hiring.Value,
		Posting = player.leaderstats.Posting.Value,
		Public = player.leaderstats.Public.Value
	}

	savePlayerData(player, playerData)
end)


VIDEO:


DEVLOG HISTORY:

Devlog 1: Saving String Values - To Be Determined


SOLUTION’S LEADERBOARD:

1st: TO BE DETERMINED

2nd: TO BE DETERMINED

3rd: TO BE DETERMINED

All replies are greatly appreciated!

1 Like

did you check the output? also instead of using player.leaderstats i recommend you use `player:WaitForChild(“leaderstats”). leaderstats does not instantly appear inside of player when it joins, so it’s best to use :WaitForChild, just in case.

Datastores can save strings completely fine. It’s that there is a problem that Roblox added when regarding SignalBehavior. It should not affect all events.

CURRENT SCRIPT:

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local DataStore = DataStoreService:GetDataStore("YourGameName")

-- Function to load player data
local function loadPlayerData(player)
	local key = "Player_" .. player.UserId

	local success, data = pcall(function()
		return DataStore:GetAsync(key)
	end)

	if success then
		return data
	else
		warn("Failed to load data for player " .. player.Name)
		return nil
	end
end

-- Function to save player data
local function savePlayerData(player, data)
	local key = "Player_" .. player.UserId

	local success, errorMessage = pcall(function()
		DataStore:SetAsync(key, data)
	end)

	if not success then
		warn("Failed to save data for player " .. player.Name .. ": " .. errorMessage)
	end
end

-- Create leaderstats and set initial values
local function setupLeaderstats(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"

	local forHire = Instance.new("StringValue")
	forHire.Name = "ForHire"
	forHire.Value = "No"
	forHire.Parent = leaderstats

	local hiring = Instance.new("StringValue")
	hiring.Name = "Hiring"
	hiring.Value = "No"
	hiring.Parent = leaderstats

	local posting = Instance.new("StringValue")
	posting.Name = "Posting"
	posting.Value = "No"
	posting.Parent = leaderstats

	local public = Instance.new("StringValue")
	public.Name = "Public"
	public.Value = "No"
	public.Parent = leaderstats

	leaderstats.Parent = player
end

-- Connect the function to player added event
Players.PlayerAdded:Connect(function(player)
	local playerData = loadPlayerData(player)

	if not playerData then
		setupLeaderstats(player)
	else
		-- Set values from loaded data
		player:WaitForChild("leaderstats").ForHire.Value = playerData.ForHire
		player:WaitForChild("leaderstats").Hiring.Value = playerData.Hiring
		player:WaitForChild("leaderstats").Posting.Value = playerData.Posting
		player:WaitForChild("leaderstats").Public.Value = playerData.Public
	end
end)

-- Connect the function to player removing event to save data
Players.PlayerRemoving:Connect(function(player)
	local playerData = {
		ForHire = player:WaitForChild("leaderstats").ForHire.Value,
		Hiring = player:WaitForChild("leaderstats").Hiring.Value,
		Posting = player:WaitForChild("leaderstats").Posting.Value,
		Public = player:WaitForChild("leaderstats").Public.Value
	}

	savePlayerData(player, playerData)
end)

THE PROBLEM:

It still doesn’t save at all. I’ve tried both your solutions.

VIDEO:

This should help: https://youtu.be/bMM1z1KAS74

This would work in a normal server. If you want this to work in Studio consider adding game:BindToClose() as Studio closes the server before data can save:

game:BindToClose(function()
task.wait(3) -- holds server open for 3 seconds
end)

Solution leaderboard? what

It doesn’t work in a normal server both ways, I join and everything works perfectly fine. But once I leave and rejoin, the leaderstats just doesn’t show up…

Current Script:

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local DataStore = DataStoreService:GetDataStore("ABCD")

-- Function to load player data
local function loadPlayerData(player)
	local key = "Player_" .. player.UserId

	local success, data = pcall(function()
		return DataStore:GetAsync(key)
	end)

	if success then
		return data
	else
		warn("Failed to load data for player " .. player.Name)
		return nil
	end
end

-- Function to save player data
local function savePlayerData(player, data)
	local key = "Player_" .. player.UserId

	local success, errorMessage = pcall(function()
		DataStore:SetAsync(key, data)
	end)

	if not success then
		warn("Failed to save data for player " .. player.Name .. ": " .. errorMessage)
	end
end

-- Create leaderstats and set initial values
local function setupLeaderstats(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"

	local forHire = Instance.new("StringValue")
	forHire.Name = "ForHire"
	forHire.Value = "No"
	forHire.Parent = leaderstats

	local hiring = Instance.new("StringValue")
	hiring.Name = "Hiring"
	hiring.Value = "No"
	hiring.Parent = leaderstats

	local posting = Instance.new("StringValue")
	posting.Name = "Posting"
	posting.Value = "No"
	posting.Parent = leaderstats

	local public = Instance.new("StringValue")
	public.Name = "Public"
	public.Value = "No"
	public.Parent = leaderstats

	leaderstats.Parent = player
end

-- Connect the function to player added event
Players.PlayerAdded:Connect(function(player)
	local playerData = loadPlayerData(player)

	if not playerData then
		setupLeaderstats(player)
	else
		-- Set values from loaded data
		player:WaitForChild("leaderstats").ForHire.Value = playerData.ForHire
		player:WaitForChild("leaderstats").Hiring.Value = playerData.Hiring
		player:WaitForChild("leaderstats").Posting.Value = playerData.Posting
		player:WaitForChild("leaderstats").Public.Value = playerData.Public
	end
end)

-- Connect the function to player removing event to save data
Players.PlayerRemoving:Connect(function(player)
	local playerData = {
		ForHire = player:WaitForChild("leaderstats").ForHire.Value,
		Hiring = player:WaitForChild("leaderstats").Hiring.Value,
		Posting = player:WaitForChild("leaderstats").Posting.Value,
		Public = player:WaitForChild("leaderstats").Public.Value
	}

	savePlayerData(player, playerData)
end)

Oh this is easy! You just need to use remote events!

Try something like this:

local DataStoreService = game:GetService("DataStoreService")
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local runService = game:GetService("RunService")

local DataStore = DataStoreService:GetDataStore("UnofficialDataStorage")

local leaderstatValues = {
	"ForHire",
	"Hiring",
	"Posting",
	"Public"
}

for i, valueName in leaderstatValues do
	local remoteEvent = Instance.new("RemoteEvent")
	remoteEvent.Name = valueName
	remoteEvent.Parent = ReplicatedStorage

	remoteEvent.OnServerEvent:Connect(function(player, value)
		if not value or type(value) ~= "boolean" then
			return
		end

		player.leaderstats[valueName].Value = value and "Yes" or "No"
	end)
end

-- Function to load player data
local function loadPlayerData(player)
	local key = player.UserId

	local success, errorMessage = pcall(function()
		return DataStore:GetAsync(key)
	end)

	if success then --no errors
		print("Player data loaded successfully for", player.Name)
		return errorMessage -- error message only if failed, return value if it didn't
	elseif not success and errorMessage then
		warn("Failed to load data for player " .. player.Name .. ": " .. errorMessage)
	end
end
-- Function to save player data
local function savePlayerData(player, data)
	local key = player.UserId

	local success, errorMessage = pcall(function()
		DataStore:SetAsync(key, data)
	end)

	if success then
		print("Player data saved successfully for", player.Name)
	else
		warn("Failed to save data for player " .. player.Name .. ": " .. errorMessage)
	end
end

-- Create leaderstats and set initial values
local function setupLeaderstats(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"

	for i, valueName in leaderstatValues do
		local stringValue = Instance.new("StringValue")
		stringValue.Name = valueName
		stringValue.Value = "No"
		stringValue.Parent = leaderstats
	end

	leaderstats.Parent = player
end

-- Connect the function to player added event
Players.PlayerAdded:Connect(function(player)
	local playerData = loadPlayerData(player)

	setupLeaderstats(player)

	if playerData then
		player:WaitForChild("leaderstats").ForHire.Value = playerData.ForHire;
		player:WaitForChild("leaderstats").Hiring.Value = playerData.Hiring;
		player:WaitForChild("leaderstats").Posting.Value = playerData.Posting;
		player:WaitForChild("leaderstats").Public.Value = playerData.Public;
	end
end)

Players.PlayerRemoving:Connect(function(player)
	local playerData = {
		ForHire = player:WaitForChild("leaderstats").ForHire.Value,
		Hiring = player:WaitForChild("leaderstats").Hiring.Value,
		Posting = player:WaitForChild("leaderstats").Posting.Value,
		Public = player:WaitForChild("leaderstats").Public.Value
	}

	savePlayerData(player, playerData)
end)

game:BindToClose(function()
	if runService:IsStudio() then task.wait(3) return end

	for _, player in Players:GetPlayers() do
		local playerData = {
			ForHire = player:WaitForChild("leaderstats").ForHire.Value,
			Hiring = player:WaitForChild("leaderstats").Hiring.Value,
			Posting = player:WaitForChild("leaderstats").Posting.Value,
			Public = player:WaitForChild("leaderstats").Public.Value
		}

		savePlayerData(player, playerData)
	end

	task.wait(3)
	print("Server shutting down. Player data saved.")
end)

And try something like this for No Button:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("Posting")

script.Parent.MouseButton1Click:Connect(function()
	script.Parent.TextColor3 = Color3.fromRGB(255,67,67)
	script.Parent.Parent.YesButton.TextColor3 = Color3.fromRGB(173, 173, 173)
	script.Parent.Parent.Parent.Parent.Parent.Stats.ForHire.ForHireLabel.Text = "NO"
	script.Parent.Parent.Parent.Parent.Parent.Stats.ForHire.ForHireLabel.TextColor3 = Color3.fromRGB(255,67,67)
	RemoteEvent:FireServer(false)
end)

and this for Yes Button:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("Hiring")

script.Parent.MouseButton1Click:Connect(function()
	script.Parent.TextColor3 = Color3.fromRGB(85, 255, 127)
	script.Parent.Parent.NoButton.TextColor3 = Color3.fromRGB(173, 173, 173)
	script.Parent.Parent.Parent.Parent.Parent.Stats.ForHire.ForHireLabel.Text = "YES"
	script.Parent.Parent.Parent.Parent.Parent.Stats.ForHire.ForHireLabel.TextColor3 = Color3.fromRGB(85,255,127)
	RemoteEvent:FireServer(true)
end)

Good luck on your journey!

Wow it worked! Thank you so much!

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