Global Table returning as nil

Trying to create a temporary player data system, that will wipe player data after they’ve left the game for an hour. The table is stored with _G, and other scripts can access it as they progress in the game and gather more tools in that server.

Every time I try to access the table using _G, it returns as nil, doesn’t work in the script posted below, nor when using the command bar under the server.

I’ve tried looking for DevForum posts to solve this problem. All DevForum posts I’ve found are irrelevant and don’t relate to the issue I’m having.

Code is below:

local GameTools = game.ServerStorage.GameTools.CreditTools

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("TempToolTimer")
local TempToolData = DataStoreService:GetDataStore("TempTools")

_G.ServerPlayerData = {
	Example = {
		"SpeedCoil",
		"GravityCoil",
		"Taser",
		"Flashlight"
	}
}

game.Players.PlayerAdded:Connect(function(Player)
	local Time = DataStore:GetAsync("TempToolTimer" .. Player.UserId) 
	if Time then
		if (os.time() - Time) < 3600 then 
			table.insert(_G.ServerPlayerData, DataStore:GetAsync("TempTools"))
		elseif (os.time() - Time > 3600) then
			table.insert(_G.ServerPlayerData, Player.Name)
		end
	else
		table.insert(_G.ServerPlayerData, Player.Name)
	end
	Player.CharacterAdded:Connect(function()
		for I,V in pairs(_G.ServerPlayerData[Player.Name]) do
			if GameTools:FindFirstChild(tostring(I)) then
				local Tool = V:Clone()
				Tool.Parent = Player.Backpack
			end
		end
	end)
end)

game.Players.PlayerRemoving:Connect(function(Player)
	DataStore:SetAsync("TempToolTimer" .. Player.UserId, os.time())
	DataStore:SetAsync("TempTools" .. Player.UserId, _G.PlayerName[Player.Name])
	wait()
	table.remove(_G.PlayerName, Player.Name)
end)```
1 Like

You just want to store the players name in the table? Or you want to store a table with the players data in the _G.ServerPlayerData?

Trying to save the Player’s Tools under _G.ServerPlayerData

I assume Example will be the player, and the values will be the data


right now you are simply inserting the players name as an array value to _G.ServerPlayerData, your result would look like

_G.ServerPlayerData = {
      Shedletsky,
      John,
      Player1
}

You want to insert a dictionary with the player as the key, wherever you do table.insert do

_G.ServerPlayerData[player] = {}

If you use a dictionary you have to index with [key] if you use an array you index with [number]

you want to use a dictionary not an array

Well, first off I can see that you’re using table.insert and then attempting to access the table like a dictionary, you cannot index table[playerName] if you’re going to be inserting the elements. I also suggest modularizing this setup instead of using _G since that isn’t exactly the best way to go about doing this as it is unnecessary.

Second of all, in your PlayerRemoving event, you’re indexing a different table identified as PlayerName and not ServerPlayerData.

I’m not very keen on these terms but I’ll try my best to understand them, so after _G.Player = {} is defined, would I use table.insert() to insert the tool names as a string into _G.Player = {}?

I’ll write out the whole thing for you give me one sec

1 Like

I’ll look into using Modules, thanks. As for the error under Player.Removed, before posting this thread I had changed the name of the Table, and replaced the Values across the script, must’ve forgotten that one. Thanks for letting me know.

1 Like

Okay there were a bunch of things to fix

code
local GameTools = game.ServerStorage.GameTools.CreditTools

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("TempToolTimer")
local TempToolData = DataStoreService:GetDataStore("TempTools")

_G.ServerPlayerData = {
	Example = {
		"SpeedCoil",
		"GravityCoil",
		"Taser",
		"Flashlight"
	}
}

game.Players.PlayerAdded:Connect(function(Player)
	
	local TempTools
	local Time 
	
	local success,err = pcall(function() -- wrapping both these datastore calls in pall 
		Time = DataStore:GetAsync("TempToolTimer" .. Player.UserId)
		TempTools = DataStore:GetAsync("TempTools".. Player.UserId)-- I added the player id in this line, it wasn't in your original code
	end)
	
	-- you can handle datastore error here

	
	if Time then
		if (os.time() - Time) < 3600 then 
			_G.ServerPlayerData[Player] = TempTools 
		elseif (os.time() - Time > 3600) then
			_G.ServerPlayerData[Player] = {} -- create empty table for players tools (we are using Player as index)
		end
	else
		_G.ServerPlayerData[Player] = {}
	end
	
	
	Player.CharacterAdded:Connect(function()
		for I,V in pairs(_G.ServerPlayerData[Player]) do
			if GameTools:FindFirstChild(tostring(I)) then
				local Tool = V:Clone()
				Tool.Parent = Player.Backpack
			end
		end
	end)
end)

game.Players.PlayerRemoving:Connect(function(Player)
	
	local success,err = pcall(function()
		DataStore:SetAsync("TempToolTimer" .. Player.UserId, os.time())
		DataStore:SetAsync("TempTools" .. Player.UserId, _G.PlayerName[Player])
	end)
	
	wait()
	_G.PlayerName[Player] = nil
end)

As @Nodehayn said you might want to use Modules, but this code works.

2 Likes

Thank you so much for the help!

1 Like

Every report I’ve gotten has been with a player already in game with the Roblox window in the forefront. Regardless, even if you do click another game on the website while in your current one, it’ll kick you out of your current one before joining the new one but it won’t do it with a disconnected message. It will close the window entirely and open a new one.