Trouble with my mass pet deletion script

Hello! This may sound confusing the way I word this, but here you go.

The issue I am having is to do with “mass pet deletion,” if you get what I mean. You select the option to mass delete pets, click on the ones you want to delete, and confirm. I got that down. I scripted it, however I’m having this issue that I haven’t been able to figure out for hours.

On the client, I have a table of unique pet ids that gets added on to with my UpdatePets() function. This function makes the pet buttons, etc. Once the player clicks on the Mass Delete Pets button, I add every pet id to the table they selected. That works fine.
Adding to the table looks like this:

if petids[petID] then -- checks if the pet id is already in the table and removes it
   petids[petID] = nil
else
   petids[petID] = true
end

You shouldn’t need the rest of the updatepets function code, since that is irrelevant. Now for real main case, I believe it to be the server. I use a remotefunction to handle this. I have tried SOOO many ways to try and delete these pets and it just doesnt work for me.

I send it to the client this way:

local listOfPets = {}
for petId in next, petids do
    listOfPets[#listOfPets + 1] = petId -- makes it so it adds the ID to the table and not "true"
end

game.ReplicatedStorage.RemoteFunctions.Function:InvokeServer("MassDeletPets",listOfPets)

On the Server I have tried this:

if type(...) == 'table' then --  ... is variadic arguments since I use 1 remote func.
   	for k,m in pairs(PlayerData['petInventory']) do
		if m["ID"] then -- pet GUID
		local Found = false
		for z,x in pairs(...) do -- returns the table just fine received from the client ( 1 GUID, 2 GUID, etc)
			if rawequal(x, m['ID']) then -- x is the GUID.
			Found = true
			break
		end
                if Found == true then 
		       PlayerData['petInventory'][k] = nil -- remove the pet index from their inventory if the id of the pet and ... table are the same.
	        else
		       print("?") -- prints the second time, and i dont know why.
                end
	end
	
end

That isn’t my only method, but just an example. I have printed/debugged a ton and came to figure it can not be the client. I’ve looped through both sides of the spectrum (server and client) and they both returned the same. e.g, 4 pets selected and sent to the server returned the same format (1 GUID, 2 GUID), etc.

Just to add on, it bugs if I don’t select EVERY pet in my inventory. I printed in my UpdatePets() function when i loop through their inventory and it looks like for example if I had 6 pets, tried to delete 4, it would print the index 5,6 and not 1,2. Doing for i = 1, #petData printed (1, nil). So I am so confused!!

If this is too long of a message, DM on discord Jaben#9847 or ask for video/screenshots. It’s hard to provide all this since it can be confusing if not written well enough

Are you sure it’s not because you’re missing an extra end keyword?

You only have one for the if and for blocks in:

for z,x in pairs(...) do -- returns the table just fine received from the client ( 1 GUID, 2 GUID, etc)
	if rawequal(x, m['ID']) then -- x is the GUID.
		Found = true
		break
end

Definitely sure, that’s just a small format copy paste issue. Not the problem though.

I see then. The other issue with the segment was that calling ... in a remote invocation function would return a userdata value instead of a table, but I’ll go with the assumption that calling ... returns a table anyways.

As I understand the server segment as is:

  1. Iterate through player’s pet inventory
  2. Iterate through the “ListOfPets” table for each pet in Player’s inventory
  3. If an id match is found, remove by setting value at index to nil

This creates the scenario where the indexes in the player’s pet inventory are nonconsecutive, and I assume that is the problem here. Is my understanding correct?

Yes, since deleting not every pet in their inventory at once turns into a nonconsecutive order of index - so like you have 5 pets, delete 3, it leaves the index at 4,5.

For example, doing that for me shows the error output like this:

for i = 1, #petInventory do
     print(i, petInventory[i]) -- 1, nil
end

for i,v in pairs(petInventory) do
      print(i,v["ID"]) -- e.g, 4 GUID, 5 GUID
end

Thing is, every other “deletion” for me works as all i do is iterate the same way. (delete a certain pet, delete all unlocked, etc). So even though the … table is returned correctly, I am not sure why my method is not working and rather breaking.

EDIT: Also tried limiting it to just a very basic loop. (on the server)

for i,v in pairs(...) do
    petInventory[i] = nil
end

Result:
image (# loop is 1,nil, pairs loop is 5,6). Selected 4/6 pets.

Yeah… lua tables don’t automatically shift elements down when you set the value at an integer index to nil.

You should probably look into utilizing the table.remove() function to remove elements from a table. It automatically shifts the indexes down as needed, so its the best way to preserve index order.

1 Like

I just tried table.remove() in that same loop above. For some reason, selecting every pet did not error, however it didnt remove all of them? I had 7 pets, selected all, only removed 5 with 2 remaining. However, their own index was correct. Maybe I didn’t write it correctly, but this is my code:

if type(...) == "table" then
	for k,m in pairs(...) do
	     table.remove(PlayerData['petInventory'], k)
	end
end

I was thinking more of this instead:

if type(...) == "table" then
	for k=#(...),1,-1 do
	     table.remove(PlayerData['petInventory'], k)
	end
end

EDIT: Traversing backwards is the key here to avoid skipping over indexes.

1 Like

That works! I usually don’t write for loops in that sense, nor think of it. But I do completely understand what it means. Thank you for spending time to help me!

1 Like