Hello! I’m wondering - should I use event connections inside a server script instead of using a debounce table for each player?
Also, how can I use connection:Disconnect() for a specific player in this part of the script?
elseif keycard:GetAttribute("KeycardReader") then
local prompt = keycard.prompt.ProximityPrompt
if prompt then
prompt.Triggered:Connect(function(player)
if player.Character:FindFirstChild("Keycard") then
print("checked")
end
end)
end
end
Here’s the full script:
local function setupKeycard(keycard)
if keycard:GetAttribute("Keycard") then
local clickDetector = keycard:FindFirstChild("ClickDetector")
local connection
if clickDetector then
connection = clickDetector.MouseClick:Connect(function(player)
if not player.Backpack:FindFirstChild("Keycard") and not player.Character:FindFirstChild("Keycard") then
local toolClone = keycardTool:Clone()
toolClone.Parent = player.Backpack
end
end)
end
elseif keycard:GetAttribute("KeycardReader") then
local prompt = keycard.prompt.ProximityPrompt
if prompt then
prompt.Triggered:Connect(function(player)
if player.Character:FindFirstChild("Keycard") then
print("checked")
end
end)
end
end
end
This is basically a script for a keycard reader, and it’s located in ServerScriptService.
I’ve used connections before in single-player setups (like conn:Disconnect()), but I’m not sure whether I should use connections here for each player and store them in a table, or just use a debounce table instead.
I need this event to be triggered only once - when a player successfully scans their keycard.
You may be able to accomplish this by doing the following:
local PlayerConns = {} -- Universal table for players
local function AddPlayerConns(PlyrName, ConnType, Conn)
if Conn ~= nil and Conn.Connected then -- Is the connection not nil and is it connected?
PlayerConns[PlyrName][ConnType] = Conn -- Add to the table
end
end
local function KillConnType(ConnType)
for PlyrName, Data in pairs(PlayerConns) do -- Loop through the present connections
for Type, Conn in pairs(Data) do -- Loop through the player's personal table
if Type == ConnType then -- Does this one have the connection?
PlayerConns[PlyrName][Type] = nil -- Remove from the table
Conn:Disconnect() -- Disconnect the event
end
end
end
end
local function SetUpKeycard(keycard)
local Conn = nil
if keycard:GetAttribute("Keycard") then
local clickDetector = keycard:FindFirstChild("ClickDetector")
if clickDetector then
Conn = clickDetector.MouseClick:Connect(function(player)
if not player.Backpack:FindFirstChild("Keycard") and not player.Character:FindFirstChild("Keycard") then
local toolClone = keycardTool:Clone()
toolClone.Parent = player.Backpack
KillConnType("Red Keycard")
end
end)
end
elseif keycard:GetAttribute("KeycardReader") then
local prompt = keycard.prompt.ProximityPrompt
if prompt then
Conn = prompt.Triggered:Connect(function(player)
if player.Character:FindFirstChild("Keycard") then
print("checked")
KillConnType("Red Keycard")
end
end)
end
end
for _, plyr in ipairs(game.Players:GetPlayers()) do
AddPlayerConns(plyr.Name, "Red Keycard", Conn)
end
end
game.Players.PlayerAdded:Connect(function(plyr)
PlayerConns[plyr.Name] = {} -- Adds a reference for the player
end)
game.Players.PlayerRemoving:Connect(function(plyr)
for _, Conn in pairs(PlayerConns[plyr.Name]) do
Conn:Disconnect() -- Disconnect all the player's connections
end
PlayerConns[plyr.Name] = nil -- Remove their reference
end)
I have another question. I want to set up the keycard when the player reaches a certain checkpoint - I have an attribute for this.
Should I track the attribute change in a LocalScript and then fire a RemoteEvent to the server once the player reaches the checkpoint (and have the server verify it before setting up the keycard)? Or should I handle everything on the server instead? I’m just trying to figure out the most resource-efficient way to do this.
Well, using a connection table per player or per object can be cleaner than trying to manage a debounce array for multiple players. With connections, you can disconnect a specific player’s listener.
At the core, both approaches are just using a table to track state.
In your script, the prompt.Triggered:Connect returns a connection, but you never store it. Without storing it, you cannot call :Disconnect() later.
Unless it’s GUI logic I wouldn’t trust the client with that.
Client → you’re relying on the player to tell the server the truth.
Server → you can validate that what they did was “legal” (with the exception of when client verification is necessary).
Yes, 100%.
I’d say make the program functional for the time being (and thinking critically on it) and then optimize later. As a Donald Knuth had stated, premature optimization is the root of all evil (or at least most of it) in programming.