local Players = game:GetService("Players")
local PlayerNameText = script.Parent.PlayerNameText
local myServerName
local InServer = false
local PlayerName = ""
game:GetService("ReplicatedStorage").JoinServers.JoinServerPlayer.OnClientEvent:Connect(function()
InServer = true
for i, player in pairs(game.Players:GetPlayers()) do
if not script.Parent:FindFirstChild(player.Name) then
local playerTextClone = PlayerNameText:Clone()
playerTextClone.Text = player.Name
playerTextClone.Parent = script.Parent
playerTextClone.Name = player.Name
-- PlayerName = plrname -- Don't understands what is this for
-- InServer = false
end
end
print(InServer)
end)
game:GetService("ReplicatedStorage").ServerNames.OnClientEvent:Connect(function(player, ServerName)
-- Invokes in ServerIDHandler
print(ServerName .. "PLAYERS SCRIPT")
myServerName = ServerName
end)
game.ReplicatedStorage.CreateServers.CreateServerPlayer.OnClientEvent:Connect(function(plr)
local label = PlayerNameText
label.Text = plr.Name
label.Parent = script.Parent
InServer = true
end)
game.ReplicatedStorage.PLRNames.OnClientEvent:Connect(function(plrname)
task.wait(0.1)
if InServer == true then
print(tostring(plrname))
local playerTextClone = PlayerNameText:Clone()
playerTextClone.Text = tostring(plrname)
playerTextClone.Parent = script.Parent
playerTextClone.Name = plrname
PlayerName = plrname
-- InServer = false
else
print("Player is not in server")
end
end)
game.ReplicatedStorage.CloseFunction.LeaveServer.OnClientEvent:Connect(function(player)
if Players.LocalPlayer.Name == myServerName then
print("PlayerNameText is not getting destroyed because the player is the server creator")
else
local PlayerTextClone = script.Parent:FindFirstChild(Players.LocalPlayer.Name)
InServer = false
PlayerTextClone:Destroy()
end
end)
Well I see you have two events connected to a function that clone UI objects. You’re also doing it inside a for loop, which the for loop will activate once for the client that was already in the game with the newly gained 2 player server, aka firing twice. Let me see the server script where you fire these events to the client.
Personally I would take the cloning outside of a for loop and just fire an event for each time someone joins and leaves so I know which person to add or delete instead of complicating it with every player.
Note that in these server scrips some sections are for different remotes
MaxPlayers:
local ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local MaxPlayersFolder = ServerScriptService.MaxPlayers.MaxPlayersFolder
ReplicatedStorage.MaxPlayers.OnServerInvoke = function(player)
local MaxPlayersValue = Instance.new("NumberValue")
MaxPlayersValue.Parent = MaxPlayersFolder
MaxPlayersValue.Value = 1
MaxPlayersValue.Name = player.Name .. " 's Server"
print(player)
if MaxPlayersValue then
return true
else
return false
end
end
ReplicatedStorage.JoinServers.JoinServerServer.OnServerEvent:Connect(function(player)
ReplicatedStorage.PLRNames:FireAllClients(player.Name)
local MaxPlayerValue = MaxPlayersFolder:FindFirstChild(player.Name .. " 's Server")
if MaxPlayerValue then
MaxPlayerValue.Value = MaxPlayerValue.Value + 1
if MaxPlayerValue.Value >5 then
print("more than five players")
end
end
end)
ReplicatedStorage.CloseFunction.CloseServerUI.OnServerEvent:Connect(function(player)
local MaxPlayerValue = MaxPlayersFolder:FindFirstChild(player.Name .. " 's Server")
if MaxPlayerValue then
MaxPlayerValue.Value = MaxPlayerValue.Value - 1
end
end)local ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local MaxPlayersFolder = ServerScriptService.MaxPlayers.MaxPlayersFolder
ServerIDHandler
local ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerIDHandler = ServerScriptService:FindFirstChild("ServerIDHandler") or Instance.new("Folder", ServerScriptService)
ServerIDHandler.Name = "ServerIDHandler"
local ListofIds = ServerIDHandler:FindFirstChild("ListofIds") or Instance.new("Folder", ServerIDHandler)
ListofIds.Name = "ListofIds"
ReplicatedStorage.CreateServers.CreateServer.OnServerInvoke = function(player)
print("CreateServer")
local ServerID = tostring(math.random(10000, 99999))
local ServerEntry = Instance.new("StringValue")
ServerEntry.Value = ServerID
ServerEntry.Name = player.Name .. " 's Server"
ServerEntry.Parent = ListofIds
local ServerName = Instance.new("StringValue")
ServerName.Name = player.Name
ServerName.Value = player.Name.. "'s SERVER"
ServerName.Parent = ServerScriptService.ServerIDHandler.ServerNames
-- set the parent as the last property because it's more optimized
for _, ReceivePlayer in ipairs(game.Players:GetPlayers()) do
game:GetService("ReplicatedStorage").ServerNames:FireAllClients(ReceivePlayer, player.Name, ServerName.Name)
print("for loop")
end
player.AncestryChanged:Connect(function()
if not player.Parent then
local playerServerID = ListofIds:FindFirstChild(player.Name .. " 's Server")
if playerServerID then
playerServerID:Destroy()
end
end
end)
return ServerID
end
ReplicatedStorage.JoinServers.JoinServer.OnServerInvoke = function(player, ServerID)
for _, server in ipairs(ListofIds:GetChildren()) do
if server.Value == ServerID then
print(player.Name .. " successfully joined server with ID:", ServerID)
ReplicatedStorage.JoinServers.JoinServerPlayer:FireClient(player)
return true
end
end
warn(player.Name .. " failed to join server with ID:", ServerID)
return false
end
ReplicatedStorage.CreateServers.CreateServerServer.OnServerEvent:Connect(function(player)
ReplicatedStorage.CreateServers.CreateServerPlayer:FireAllClients(player)
end)
ReplicatedStorage.CloseFunction.CloseServerUI.OnServerEvent:Connect(function(player)
ReplicatedStorage.CloseFunction.LeaveServer:FireAllClients(player)
end)
I have updated the script so it debounces, but it still duplicates the player who joined the server’s text label
Local script:
-- Create a wait variable to debounce the cloning of the text label
local debounce = false
local Players = game:GetService("Players")
local PlayerNameText = script.Parent.PlayerNameText
local myServerName
local InServer = false
local PlayerName = ""
game:GetService("ReplicatedStorage").JoinServers.JoinServerPlayer.OnClientEvent:Connect(function()
if not debounce then
debounce = true
wait(1)
debounce = false
InServer = true
for i, player in pairs(game.Players:GetPlayers()) do
if not script.Parent:FindFirstChild(player.Name) then
local playerTextClone = PlayerNameText:Clone()
playerTextClone.Text = player.Name
playerTextClone.Parent = script.Parent
playerTextClone.Name = player.Name
end
end
end
end)
--
game:GetService("ReplicatedStorage").ServerNames.OnClientEvent:Connect(function(player, ServerName)
-- Invokes in ServerIDHandler
print(ServerName .. "PLAYERS SCRIPT")
myServerName = ServerName
end)
game.ReplicatedStorage.CreateServers.CreateServerPlayer.OnClientEvent:Connect(function(plr)
local label = PlayerNameText
label.Text = plr.Name
label.Parent = script.Parent
InServer = true
end)
game.ReplicatedStorage.PLRNames.OnClientEvent:Connect(function(plrname)
task.wait(0.1)
if InServer == true then
print(tostring(plrname))
local playerTextClone = PlayerNameText:Clone()
playerTextClone.Text = tostring(plrname)
playerTextClone.Parent = script.Parent
playerTextClone.Name = plrname
PlayerName = plrname
-- InServer = false
else
print("Player is not in server")
end
end)
game.ReplicatedStorage.CloseFunction.LeaveServer.OnClientEvent:Connect(function(player)
if Players.LocalPlayer.Name == myServerName then
print("PlayerNameText is not getting destroyed because the player is the server creator")
else
local PlayerTextClone = script.Parent:FindFirstChild(Players.LocalPlayer.Name)
InServer = false
PlayerTextClone:Destroy()
end
end)
This will mean you’ll have to store the names another way, or use the method I suggested and only fire once per player joining and once per player leaving and just FireAllClients with the person’s name as the index, so the clients know which person to add or destroy from the UI.
I believe it would fix your issue.
For example if you were to put a fireallclient inside a for loop getting the table of players, its going to FireAllClients to every single client for the amount of players in the game as the count of Event fires.
Would I need to replace :FireAllClients to :FireClient?
Like this:
for _, ReceivePlayer in ipairs(game.Players:GetPlayers()) do
game:GetService("ReplicatedStorage").ServerNames:FireClient(ReceivePlayer, player.Name, ServerName.Name)
print("for loop")
end
Is it because of the debounce in the local script?
-- Create a wait variable to debounce the cloning of the text label
local debounce = false
local Players = game:GetService("Players")
local PlayerNameText = script.Parent.PlayerNameText
local myServerName
local InServer = false
local PlayerName = ""
game:GetService("ReplicatedStorage").JoinServers.JoinServerPlayer.OnClientEvent:Connect(function()
if not debounce then
debounce = true
wait(1)
debounce = false
InServer = true
for i, player in pairs(game.Players:GetPlayers()) do
if not script.Parent:FindFirstChild(player.Name) then
local playerTextClone = PlayerNameText:Clone()
playerTextClone.Text = player.Name
playerTextClone.Parent = script.Parent
playerTextClone.Name = player.Name
end
end
end
end)
--
game:GetService("ReplicatedStorage").ServerNames.OnClientEvent:Connect(function(player, ServerName)
-- Invokes in ServerIDHandler
print(ServerName .. "PLAYERS SCRIPT")
myServerName = ServerName
end)
game.ReplicatedStorage.CreateServers.CreateServerPlayer.OnClientEvent:Connect(function(plr)
local label = PlayerNameText
label.Text = plr.Name
label.Parent = script.Parent
InServer = true
end)
game.ReplicatedStorage.PLRNames.OnClientEvent:Connect(function(plrname)
task.wait(0.1)
if InServer == true then
print(tostring(plrname))
local playerTextClone = PlayerNameText:Clone()
playerTextClone.Text = tostring(plrname)
playerTextClone.Parent = script.Parent
playerTextClone.Name = plrname
PlayerName = plrname
-- InServer = false
else
print("Player is not in server")
end
end)
game.ReplicatedStorage.CloseFunction.LeaveServer.OnClientEvent:Connect(function(player)
if Players.LocalPlayer.Name == myServerName then
print("PlayerNameText is not getting destroyed because the player is the server creator")
else
local PlayerTextClone = script.Parent:FindFirstChild(Players.LocalPlayer.Name)
InServer = false
PlayerTextClone:Destroy()
end
end)
You also have some UI Cloning that doesn’t even check if they exist or not. In your JoinServerPlayer and PLRNames connections, the script clones and creates a new text element for each player without validating whether it already exists. You’re using a boolean which doesn’t get updated yet.
Example being PLRNames:
Here’s the logic I think you should have:
Player Joins Server (Using PlayerAdded signal we can connect it on the server to fire the player’s name to everyone’s client) → Our Clients receive this Event and only fire a function once per player join → if the player leaves fire another FireAllClients event telling everyone that this person left the server and destory their name if needed on the UI elements.