DataStore Script Not Saving - OOP

Hey there!

I just started using OOP and I came across a problem in the process of making a data store server script.
The issue right now, is that the system doesn’t save the player’s money. Any help is appreciated.

local ServerStorage = game:GetService("ServerStorage")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataStore")

local DataFolder = Instance.new("Folder")
DataFolder.Name = "Data"
DataFolder.Parent = ServerStorage

local PlayerData = {}
PlayerData.__index = PlayerData

function PlayerData.new(player)
	local self = setmetatable({}, PlayerData)
	self.player = player
	self.userId = "Player_" .. player.UserId
	self.data = {
		["money"] = 0
	}

	local playerDataFolder = Instance.new("Folder")
	playerDataFolder.Name = player.Name
	playerDataFolder.Parent = DataFolder

	for key, value in pairs(self.data) do
		if typeof(value) == "number" then
			local numberValue = Instance.new("NumberValue")
			numberValue.Name = key
			numberValue.Value = value
			numberValue.Parent = playerDataFolder
		elseif typeof(value) == "string" then
			local stringValue = Instance.new("StringValue")
			stringValue.Name = key
			stringValue.Value = value
			stringValue.Parent = playerDataFolder
		end
	end
	
	print(self.data)

	return self
end

function PlayerData:Load()
	local success, data = pcall(function()
		return DataStore:GetAsync(self.userId)
	end)
	if success then
		self.data = data or {
			money = 0
		}
	else
		warn(data)
	end
end

function PlayerData:Save()
	local success, err = pcall(function()
		DataStore:SetAsync(self.userId, self.data)
	end)
	if not success then
		warn(err)
	end
end

function PlayerData:ChangeData(key, value, method)
	if method == "addition" then
		self.data[key] += value
	elseif method == "substraction" then
		self.data[key] -= value
	elseif method == "multiplication" then
		self.data[key] *= value
	end
	print(self.data[key])

	local playerDataFolder = DataFolder:FindFirstChild(self.player.Name)
	if playerDataFolder then
		local dataInstance = playerDataFolder:FindFirstChild(key)
		if dataInstance then
			dataInstance.Value = value
		end
	end
end

game.Players.PlayerAdded:Connect(function(player)
	local playerData = PlayerData.new(player)
	playerData:Load()
	
	--playerData:ChangeData("money", 100, "addition")
end)

game.Players.PlayerRemoving:Connect(function(player)
	local playerData = PlayerData.new(player)
	playerData:Save()
end)

game:BindToClose(function()
	for _, player in pairs(game.Players:GetPlayers()) do
		local playerData = PlayerData.new(player)
		playerData:Save()
	end
end)

if game:GetService("RunService"):IsStudio() then
	game:BindToClose(function()
		for _, player in pairs(game.Players:GetPlayers()) do
			local playerData = PlayerData.new(player)
			playerData:Save()
		end
	end)
end
6 Likes

Could anyone help me? Also, is my use of OOP correct?

1 Like

You are creating an entirely new metatable when the Player Leaves, with inherits entirely new data along with it, you are then saving the “New Data” under the Player’s Key, With “Resets” your Data.

A Simple Solution is to Store the metatable into a Table, and then Access it once the Player is leaving to Save it, just so you dont lose it.

It appears to be so, besides the PlayerRemoving Event.

Like that?

local ServerStorage = game:GetService("ServerStorage")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataStore")

local DataFolder = Instance.new("Folder")
DataFolder.Name = "Data"
DataFolder.Parent = ServerStorage

local PlayerData = {}
PlayerData.__index = PlayerData

function PlayerData.new(player)
	local self = setmetatable({}, PlayerData)
	self.player = player
	self.userId = "Player_" .. player.UserId
	self.data = {
		money = 0
	}

	local playerDataFolder = Instance.new("Folder")
	playerDataFolder.Name = player.Name
	playerDataFolder.Parent = DataFolder

	for key, value in pairs(self.data) do
		local dataInstance
		if typeof(value) == "number" then
			dataInstance = Instance.new("NumberValue")
		elseif typeof(value) == "string" then
			dataInstance = Instance.new("StringValue")
		end

		dataInstance.Name = key
		dataInstance.Value = value
		dataInstance.Parent = playerDataFolder
	end

	print(self.data)

	return self
end

function PlayerData:Load()
	local success, data = pcall(function()
		return DataStore:GetAsync(self.userId)
	end)
	if success then
		self.data = data or {
			money = 0
		}
	else
		warn(data)
	end
end

function PlayerData:Save()
	local success, err = pcall(function()
		DataStore:SetAsync(self.userId, self.data)
	end)
	if not success then
		warn(err)
	end
end

function PlayerData:ChangeData(key, value, method)
	if method == "addition" then
		self.data[key] += value
	elseif method == "subtraction" then
		self.data[key] -= value
	elseif method == "multiplication" then
		self.data[key] *= value
	end
	print(self.data[key])

	local playerDataFolder = DataFolder:FindFirstChild(self.player.Name)
	if playerDataFolder then
		local dataInstance = playerDataFolder:FindFirstChild(key)
		if dataInstance then
			dataInstance.Value = self.data[key]
		end
	end
end

local playerDataInstances = {}

game.Players.PlayerAdded:Connect(function(player)
	local playerData = PlayerData.new(player)
	playerData:Load()
	playerDataInstances[player] = playerData
	
	--playerData:ChangeData("money", 100, "addition")
end)

game.Players.PlayerRemoving:Connect(function(player)
	local playerData = playerDataInstances[player]
	if playerData then
		playerData:Save()
		playerDataInstances[player] = nil
	end
end)

game:BindToClose(function()
	for player, playerData in pairs(playerDataInstances) do
		playerData:Save()
		playerDataInstances[player] = nil
	end
end)

if game:GetService("RunService"):IsStudio() then
	game:BindToClose(function()
		for player, playerData in pairs(playerDataInstances) do
			playerData:Save()
			playerDataInstances[player] = nil
		end
	end)
end

If so, then it doesn’t save.
Output:
image

It should work as intended, but I do not recommend having the Index as the Player Instance, but as their UserId.

That means its trying to saving the data, you are just using Sending too many Requests.

1 Like