Datastore returns nil

function UserData:LoadData(plr) -- When a user first joins we need to load is data, done via Datastore keys
	local DataStore = game:GetService("DataStoreService"):GetDataStore("Data")
	local Data = DataStore:GetAsync(plr.UserId..Datakey)
	if Data == nil then
		Data = DefaultData
	end
	local HouseArgs = {GetHouseName(plr)}
	Data.House.Name = HouseArgs[1]
	if Data.House.Name ~= "Houseless" then
		Data.House.Rank = GetHouseRank(plr,HouseArgs[2])
	else
		Data.House.Rank = "Houseless"
	end
	Data.House.HouseIcon = HouseArgs[3]
	Data.MainGroupRank = plr:GetRoleInGroup(4141896)
	wait()
	if ServerData[plr] == nil then
		ServerData[plr] = Data
	end
	print(ServerData[plr])
	DataStore:SetAsync(plr.UserId..Datakey, Data)
end

Hello! I’m using the script above to load the users data and then replicate it to ServerData! I was wondering why whenever I print or try to use ServerData it returns nil? Am I doing something wrong?

Not once is ServerData defined. Did you mean Data?

2 Likes

There is more to the script then that.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Modules = ReplicatedStorage:WaitForChild("Modules")
local Houses = require(Modules:WaitForChild("Houses"))
local UserData = {}
local ServerData = {}
local Datakey = 150 -- Changing this will reset all of the users currency, etc.
local DefaultData = { -- Datastore including the users Currency, House, House Rank, and Profile information
	['House'] = {
		['Name'] = nil; -- Resulting to NIL. This isn't needed but is good for organization. 
		['Rank'] = nil;
		['HouseIcon'] = nil;
	};
	['MainGroupRank'] = nil;
	['Currency'] = 0;
	['ProfileDescription'] = "Default Profile Description!"
};

function UserData:ChangeData(plr) -- Adding data (Player, DataType, New Value)
	local DataStore = game:GetService("DataStoreService"):GetDataStore("Data")
	local Data = DataStore:GetAsync(plr.UserId..Datakey)
end

function UserData:GetData(plr,datatype) -- Getting the dating, used for LocalScripts and Gui's
	print(ServerData[plr])
	if datatype == "HouseName" then
		return ServerData[plr].House.Name
	elseif datatype == "HouseRank" then
		return ServerData[plr].House.Rank
	elseif datatype == "Currency" then
		return ServerData[plr].Currency
	elseif datatype == "MainGroupRank" then
		return ServerData[plr].MainGroupRank
	elseif datatype == "ProfileDescription" then
		return ServerData[plr].ProfileDescription
	elseif datatype == "HouseIcon" then
		return ServerData[plr].House.HouseIcon
	end
end

function UserData:ReturnHouseData(plr) -- Returns the users house data, mainly used for localscripts and gui's
	local DataStore = game:GetService("DataStoreService"):GetDataStore("Data")
	local Data = DataStore:GetAsync(plr.UserId..Datakey)
	return Data.House.Name, Data.House.Rank
end 

local function GetHouseName(plr) -- Called during the load data process
	for index,value in pairs(Houses) do
		if plr:IsInGroup(value[1]) then
			return index,value[1],value[2] -- Id is the group id, would still need to return names, etc.. (6/24/18, CHANGED TO NAME)
		end
	end
	return "Houseless"
end

local function GetHouseRank(plr,group)
	return plr:GetRoleInGroup(group)
end

function UserData:LoadData(plr) -- When a user first joins we need to load is data, done via Datastore keys
	local DataStore = game:GetService("DataStoreService"):GetDataStore("Data")
	local Data = DataStore:GetAsync(plr.UserId..Datakey)
	if Data == nil then
		Data = DefaultData
	end
	local HouseArgs = {GetHouseName(plr)}
	Data.House.Name = HouseArgs[1]
	if Data.House.Name ~= "Houseless" then
		Data.House.Rank = GetHouseRank(plr,HouseArgs[2])
	else
		Data.House.Rank = "Houseless"
	end
	Data.House.HouseIcon = HouseArgs[3]
	Data.MainGroupRank = plr:GetRoleInGroup(4141896)
	wait()
	if ServerData[plr] == nil then
		ServerData[plr] = Data
	end
	print(ServerData[plr])
	DataStore:SetAsync(plr.UserId..Datakey, Data)
end

return UserData

Turns out when printing Data it also returns nil.
I’m simply trying to get my players Data to a localscript to put in a GUI, etc…

(UPDATE)
When loading in the player and printing the SaveData[plr] it retunrs a table…
But when using this script here…

function UserData:GetData(plr,datatype) -- Getting the dating, used for LocalScripts and Gui's
	print(ServerData[plr])
	if datatype == "HouseName" then
		return ServerData[plr].House.Name
	elseif datatype == "HouseRank" then
		return ServerData[plr].House.Rank
	elseif datatype == "Currency" then
		return ServerData[plr].Currency
	elseif datatype == "MainGroupRank" then
		return ServerData[plr].MainGroupRank
	elseif datatype == "ProfileDescription" then
		return ServerData[plr].ProfileDescription
	elseif datatype == "HouseIcon" then
		return ServerData[plr].House.HouseIcon
	end
end

Printing ServerData[plr] returns nil. “plr” is the same thing in both. I even attempted to use names (and it still printed nil)

This is done via ModuleScript

So even though I set ServerData[plr] to Data (and it prints a table which it should) then if I try to access it again it is set back to nil?

You should be making a clone the table

DefaultData

As all players with no data will share this table meaning new players data will be incorrect as the game runs

Secondly using.

plr.UserId..Datakey

Is a very poor choice in key as you just postfix 150 which could be another players UserId.
You should use something like this to ensure the key is unique.

“usr_” .. tostring(plr.UserId)

1 Like

I changed my key method (Hadn’t thought of that)

But I’m confused what you mean by clone the table? I am.

You’re not. When you pass in a table, it passes the reference instead of a new copy.

local x = { a = 1 }
local y = x
print(y.a) --1
x.a = 3
print(y.a) --3

I ended up fixing my problem by replicating/cloning the default data to the serverdata (like you said)

But I realized the its not the best idea to let the client access and view the data, so I used an InvokeServer to be the gateway and just fetched it that way. Thanks for your help!

1 Like