Removing data from a players table

TaskComplete.OnServerEvent:Connect(function(player, task)
	for i, v in pairs(TaskData) do
		if task == i then
			for _, playersTask in pairs(PlayerTasks[player.UserId]) do
				if playersTask == task then
					print(PlayerTasks[player.UserId][task])
					PlayerTasks[player.UserId][task] = nil
					print(PlayerTasks[player.UserId][task])
					UpdateCoins(player, v.Coins, true)
					UpdateExp(player, v.Exp, true)
					TaskComplete:FireClient(player, task)
				end
			end
		end
	end
end)

Basically this goes through the players task table, and if they have a task that matches the specified task then they get a reward and it should remove the task from their folder

PlayerTasks[player.UserId][task] = nil

However if I do

print(PlayerTasks[player.UserId][task])
PlayerTasks[player.UserId][task] = nil
print(PlayerTasks[player.UserId][task])

Both prints return nil

You need to show us where you create the table data.

function TaskService:AssignTask(player)
	if PlayerTasks[player.UserId] then
		if #PlayerTasks[player.UserId] >= 3 then return end

		for i, v in pairs(TaskData) do
			for _, currentTask in pairs(PlayerTasks[player.UserId]) do
				if i == currentTask then return end
			end
			
			table.insert(PlayerTasks[player.UserId], math.random(#PlayerTasks[player.UserId]), i)
			UpdateTasks:FireClient(player, false, i)
		end
	else
		PlayerTasks[player.UserId] = {}
			
		local RandomTask = chooseRandom(TaskData)
		table.insert(PlayerTasks[player.UserId], RandomTask.Key)
		UpdateTasks:FireClient(player, false, RandomTask.Key)
	end
end

You could do table.remove() to clear the table data in a specific placement. Then have the script check if the data exist. If the user has no data , have the script make new data and repeat.

1 Like

You need to know the index of the value. I don’t know how to get the values position in the table.

Doing PlayerTasks[player.UserId][task] is attempting to get the value in the table that has key task, but after reading your code, it doesn’t look like this is the case. Based on your assignment function and the if statements you’ve got, it seems that task is actually the same as the value, not the index.

Unless you have the data set up such that PlayerTasks[player.UserId][task] == task (i.e. that the key and value are the same, always) then that’s where the problem arises. You’d be better off reading the index as part of your pairs loop and use that instead of task.

So do something like:

TaskComplete.OnServerEvent:Connect(function(player, task)
	for i, v in pairs(TaskData) do
		if task == i then
			for taskIndex, playersTask in pairs(PlayerTasks[player.UserId]) do
				if playersTask == task then
					table.remove( PlayerTasks[player.UserId], taskIndex ) -- pop the task
					UpdateCoins(player, v.Coins, true)
					UpdateExp(player, v.Exp, true)
					TaskComplete:FireClient(player, task)
				end
			end
		end
	end
end)

table.remove only works in two scenarios.

  • You know the index of the value
  • You aren’t working with a dictionary

table.remove, as well as the majority of the rest of the table library, is designed to work only woth the array part of tables. In the case of a dictionary, keys are arbitrary and found in the hash part of the array, which table.remove can’t work from. It requires a numerical position to remove from, which dictionary keys do not have.

1 Like

Hello NinjoOnline,
I’ve stumbled across the same problem, however I somehow found a work-around solution in case you or other developers come across the same problem.

Please note that this only works with Arrays

API’s used: table.find(TableName, Text) & table.remove(TableName, Text)
https://developer.roblox.com/en-us/api-reference/lua-docs/table
https://developer.roblox.com/en-us/articles/Table

Example:
When a player joins, you insert their UserId. When they leave, you remove it.

TEMPLATE

--[[
1.
DEFINING THE SERVICE(S) REQUIRED (similar to import os in python, in case you learn better by connecting prior knowladge.
]]--

local PlayerService					=	game:GetService("Players")

--[[
2.
Creating a table
--]]

local DataOnTheServer				=	{}	--[[	AN EMPTY TABLE IS CREATED	]]--

--[[
3.
Using PlayerAdded/PlayerRemoving to detect/remove player data in the table.
]]--

PlayerService.PlayerAdded:Connect(function(Player)

	table.insert(DataOnTheServer, Player.UserId)

end)

PlayerService.PlayerRemoving:Connect(function(Player)

	table.remove(DataOnTheServer, table.find(DataOnTheServer, Player.UserId))

end)

To sum it up:

SOLUTION

table.remove(NameOfTable, table.find(NameOfTable, Value))

Still don’t understand it?

  1. Wishing to remove data? Yes, me too.

  2. Use table.remove(NameOfTable, Value) but Lua will not recognize the value Player.UserId, therefore WE USE table.find(NameOfTable, Value) to define the value.

You can further customize this to your liking, I’ve been tying this to datastore requests, say 10 seconds into a game, the client automatically requests it via a local script tied to a remote event.
(to make sure the player can not abuse PlayerService.PlayerAdded and PlayerRemoving)

To avoid the client to abuse the remote event (exploiters with their executors sending requests to the server by remote events), I insert their data into the table & properties like checking script validity (pass the script in the remote event, real handy), checking if they had requested it in the past, if so it would kick them.

This can easily be bypassed by calling the remote events on join via an exploiters ‘executor’, I’m working on a workaround on that.

This is just an example, get creative!

I am in no way a professional, this is a hobby. If you find solutions that help performance, do not hesitate to edit it further (:

3 Likes