DataStore Problems

I have a system in place that uses _G to save.

_G.sessionData[player.UserId] is a table for the player that joins.

_G.sessionData[player.UserId] = {
	settings = {
		FOV = 1
	},
	endings = {
		Shoplift = false,
		Breakfast = 0
	},
	secrets = {

	}
}

^ This is how the table looks like.

local DSS = game:GetService("DataStoreService")
local RS = game:GetService("ReplicatedStorage")
local BS = game:GetService("BadgeService")
local Players = game:GetService("Players")
local RuS = game:GetService("RunService")

local movement = RS.Movement

local config = require(script.Configuration)

local settingsDS = config.settingDS
local secretsDS = config.secretsDS
local endingsDS = config.endingsDS

local dataKey = config.dataKey

local defaults = config.defaults

local function GetData(player, dataStore)
	local data
	local success, result = pcall(function()
		data = dataStore:GetAsync(dataKey..player.UserId)
	end)
	if not success then
		warn(dataStore.Name.." could not load: "..result)
	end
	return data
end

local function SaveData(player, data, dataStore)
	local success, result = pcall(function()
		dataStore:SetAsync(data, dataKey..player.UserId)
	end)
	if not success then
		warn(dataStore.Name.." could not save: "..result)
	else
		print(dataStore.Name, "saved", player.Name.."'s", "data")
	end
end

_G.sessionData = {}
Players.PlayerAdded:Connect(function(player)
	player:LoadCharacter()
	movement:FireClient(player, false)
	
	_G.sessionData[player.UserId] = {}
	local plrData = _G.sessionData[player.UserId]
	
	local money = Instance.new("IntValue")
	money.Name = "Money"
	money.Parent = player
	
	local dataLoaded = Instance.new("BoolValue")
	dataLoaded.Name = "DataLoaded"
	dataLoaded.Parent = player
	
	plrData.settings = GetData(player, settingsDS) or defaults.settings
	plrData.secrets = GetData(player, secretsDS) or defaults.secrets
	plrData.endings = GetData(player, endingsDS) or defaults.endings
	
	print(plrData.endings.Shoplift)
	
	dataLoaded.Value = true
	
	local date = os.date("*t")
	if (date.hour % 24) == 4 then
		BS:AwardBadge(player.UserId, 2127043783)
	end
end)

Players.PlayerRemoving:Connect(function(player)
	local plrData = _G.sessionData[player.UserId]
	
	print(plrData.endings.Shoplift)
	SaveData(player, plrData.settings, settingsDS)
	SaveData(player, plrData.secrets, secretsDS)
	SaveData(player, plrData.endings, endingsDS)
end)

^ The script that saves and gets data. It prints when it saves.

local DSS = game:GetService("DataStoreService")

local config = {
	settingDS = DSS:GetDataStore("Settings_TESTING"),
	secretsDS = DSS:GetDataStore("Secrets_TESTING"),
	endingsDS = DSS:GetDataStore("Endings_TESTING"),
	
	dataKey = "DataKey-6-",
	
	defaults = {
		settings = {
			FOV = 1
		},
		endings = {
			Shoplift = false,
			Breakfast = 0
		},
		secrets = {

		}
	}
}

return config

^ The configuration module that I use

local RS = game:GetService("ReplicatedStorage")
local BS = game:GetService("BadgeService")

local giveEnding = RS.GiveEnding

giveEnding.Event:Connect(function(player, ending, value)
	local plrData = _G.sessionData[player.UserId]
	plrData.endings[ending] = value or true
	
	BS:AwardBadge(player.UserId, 2127044890)
end)

^ The event I use for giving a player an ending.

When I get an ending, it sets the ending variable inside the player’s session data to the value provided or true. For when I join, I print the Shoplift ending variable to see if I have it (for testing purposes). When I leave, it prints the Shoplift ending variable to tell me whether I have it or not.

When I joined, it printed false.
When I left, it printed true and saved.

But when I rejoined, it printed false again. So I don’t get it, what is preventing it from saving the table? I have avoided using DataStore2 because it failed most of the time I used it, but if it is necessary I will incorporate it.

Ah, this problem again.

So basically, when you leave too fast from the game, the DataStore will not have enough time to save. You shouldn’t save it when the player leaves, but instead add an autosave. You should only save like that when multiple players are in the server.

It prints when it saves, it always prints when I get kicked.

Put the print statement after it saves on the PlayerRemoving function, and if it doesn’t print, that means my previous post was correct.

I should’ve clarified that it prints after it saves, so no, you’re statement is incorrect.

That’s weird. Let’s see if I understand this correctly.

So, when you leave, it prints true and saves.
And, when joining back, it prints true IF it saves, but in this case, it didn’t.

That’s the problem?

It prints true if the value was set to true in the saved table. I couldn’t make out your wording but essentially yes.

Alright. So, try adding this line of code.
game:BindToClose(function()wait(5)end)
This will pause the server before it closes, for five seconds.

I am already doing this. The problem isn’t the game closing too early. It’s that it won’t save for some reason. It says it does, but when I :GetAsync() it doesn’t return the same table.

print(dataStore.Name, "saved", player.Name.."'s", "data")

does this print something in the output when you leave?

It prints after you leave and have saved.

print(dataStore.Name, "saved", player.Name.."'s data") would be more accurate.

I was quoting what was already in his code, not making my own.

1 Like