Why doesn't the __newindex run?

local players = game:GetService("Players")

local lobby = {}
local mt = {}
mt.__index = mt

function lobby.new(zone_model: Model)
	local self = {}
	setmetatable(self, mt)
	
	self.instance = zone_model
	self.level_needed = zone_model:GetAttribute("LevelNeeded")
	self.place_id = zone_model:GetAttribute("PlaceId")
	self.players = setmetatable({}, {
		__newindex = function(t, player: Player, exists: boolean)		
			print("newindex")
			if exists then
				local leave_lobby_gui = script.LeaveLobbyGUI:Clone()
				leave_lobby_gui.Parent = player.PlayerGui
				leave_lobby_gui.Container.LeaveButton.MouseButton1Click:Once(function()
					print("clicked")
					self:remove_player(player)		--> This is recursive because this function will be called, but exists boolean will be nil.
				end)
			else
				--> This will run if the leave button is clicked, or manually called by the server.
				local leave_lobby_gui = player.PlayerGui:FindFirstChild("LeaveLobbyGUI")
				if leave_lobby_gui then
					leave_lobby_gui:Destroy()
				end
			end
		
			rawset(t, player, exists)
			return t
		end,
	})
	
	local zone_area = zone_model.Zone :: BasePart
	zone_area.Touched:Connect(function(part_hit)
		self:add_player(players:GetPlayerFromCharacter(part_hit.Parent))
	end)
end

function mt:add_player(player: Player)
	if not player then return end 				--> Checking if player exists.
	
	self.players[player] = true
end

function mt:remove_player(player: Player)
	if not player then return end 				--> Checking if player exists.
	
	self.players[player] = nil
end

return lobby

This works when Touched is fired, but inside where I remove the player from the list by clicking the button just doesn’t fire the newindex function. I’m new to metatables.

The add and remove player are easy functions.

function mt:add_player(player: Player)
	if not player then return end 				--> Checking if player exists.
	
	self.players[player] = true
end

function mt:remove_player(player: Player)
	if not player then return end 				--> Checking if player exists.
	
	self.players[player] = nil
end

1 Like

As far as I know, __newindex is not fired when you remove a value from a table by setting it to nil, you may be better off doing this:

function mt:remove_player(player: Player)
	if not player then return end --> Checking if player exists.
	self.players[player] = false
end

This should still work with your if exists logic, as if statements like that will go off if a value is equal to something that’s not nil or false.

1 Like

image

Still doesn’t work. This should print newindex, clicked, newindex

I think this doesn’t work because newindex only fires when a new index is added, not when you change it.

The only way I can think this wouldn’t work is if ‘player’ is somehow not being passed into the :remove_player function, can you print the ‘Player’ value? In addition, are they the same tables for self.players? Can you also print what’s going on in the __newindex method when it’s called?

Try moving the mt table functions above the lobby function.

Fires when table[index] tries to be set (table[index] = value), if table[index] is nil…

If you are trying to have it trigger with existing keys, you need to create a proxy table that’s empty with an __index metamethod that points to your actual table and a __newindex metamethod with your mechanism.

It will look something like this:

local players = {}

self.players = setmetatable({}, {
    __index = players,
    __newindex = function(_, player: Player, exists: boolean)
        -- instead of t table, you reference players table
    end
})
2 Likes

Thank you. This is what I was looking for.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.