Updating a GUI player list based on players joining

Hi all!
To keep it brief, I’m trying to update a sort of player list when someone joins (but not leaves) the game
The code is in a server Script in Workplace, in case that is the issue.
(An example of the GUI before running, Don’t worry about Other Player 4 not having an image)

ZeroDecibelsUIALPHA2

The main problem is that It’s working, albeit inconsistently. When I run a server test with 1-2 players, it seems to work fine. 3-4 players, however, and it seems to not update at all when a player joins. I store the players into a dictionary and then get the text versions of the names using tostring() to put them into the corresponding text labels

Example of it working with 2 players: (This is the result for both players in the server)

Example of it NOT working with 4 players: (For Player1 and Player2 it only prints the Player1 and Player2 GUI. For Player4, It prints every players GUI like it should be doing)

UIissue3

--Starting values for the table
local Survivors = {
	Survivor1 = "No One" ,
	Survivor2 = "No One" ,
	Survivor3 = "No One" ,
	Survivor4 = "No One"
}

local Players = game:GetService("Players")
local StarterGUI = game:GetService("StarterGui")


-- Player 1 HUD
local otherPlayerTextOne = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayer1")
local otherPlayerBlotOne = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayer1Blot")
local otherPlayerStatusOne = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayerStatus1")
local otherPlayerLabelOne = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayerLabel1")
 
-- Player 2 HUD
local otherPlayerTextTwo = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayer2")
local otherPlayerBlotTwo = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayer2Blot")
local otherPlayerStatusTwo = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayerStatus2")
local otherPlayerLabelTwo = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayerLabel2")


-- Player 3 HUD 
local otherPlayerTextThree = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayer3")
local otherPlayerBlotThree = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayer3Blot")
local otherPlayerStatusThree = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayerStatus3")
local otherPlayerLabelThree = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayerLabel3")


-- Player 4 HUD
local otherPlayerTextFour = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayer4")
local otherPlayerBlotFour = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayer4Blot")
local otherPlayerStatusFour = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayerStatus4")
local otherPlayerLabelFour = StarterGUI:FindFirstChildOfClass("ScreenGui"):FindFirstChild("UIDragger"):FindFirstChild("OtherPlayerLabel4")

--Checks to see if the Player is a survivor, since I'm early in development, this is more of an abstraction for now
local isSurvivor = true
local amountOfSurvivors = 0

--Checks to see if Survivor slot 1 is taken or not
function isOneEnabled()
	if Survivors["Survivor1"] == "No One" then
		otherPlayerTextOne.Transparency = 1
		otherPlayerBlotOne.ImageTransparency = 1
		otherPlayerStatusOne.ImageTransparency = 1
		otherPlayerLabelOne.ImageTransparency = 1
	else
		otherPlayerTextOne.Transparency = 0
		otherPlayerBlotOne.ImageTransparency = 0
		otherPlayerStatusOne.ImageTransparency = 0
		otherPlayerLabelOne.ImageTransparency = 0 	
	end		
end

--Checks to see if Survivor slot 2 is taken or not
function isTwoEnabled()
	if Survivors["Survivor2"] == "No One"  then
		otherPlayerTextTwo.Transparency = 1
		otherPlayerBlotTwo.ImageTransparency = 1
		otherPlayerStatusTwo.ImageTransparency = 1
		otherPlayerLabelTwo.ImageTransparency = 1
	else
		otherPlayerTextTwo.Transparency = 0
		otherPlayerBlotTwo.ImageTransparency = 0
		otherPlayerStatusTwo.ImageTransparency = 0
		otherPlayerLabelTwo.ImageTransparency = 0 			
	end
		
end

--Checks to see if Survivor slot 3 is taken or not
function isThreeEnabled()
	if Survivors["Survivor3"] == "No One"  then	
		otherPlayerTextThree.Transparency = 1
		otherPlayerBlotThree.ImageTransparency = 1
		otherPlayerStatusThree.ImageTransparency = 1
		otherPlayerLabelThree.ImageTransparency = 1	
	else
		otherPlayerTextThree.Transparency = 0
		otherPlayerBlotThree.ImageTransparency = 0
		otherPlayerStatusThree.ImageTransparency = 0
		otherPlayerLabelThree.ImageTransparency = 0 				
	end	
end

--Checks to see if Survivor slot 4 is taken or not
function isFourEnabled()
	if Survivors["Survivor4"] == "No One" then	
		otherPlayerTextFour.Transparency = 1
		otherPlayerBlotFour.ImageTransparency = 1
		otherPlayerStatusFour.ImageTransparency = 1
		otherPlayerLabelFour.ImageTransparency = 1	
	else
		otherPlayerTextFour.Transparency = 0
		otherPlayerBlotFour.ImageTransparency = 0
		otherPlayerStatusFour.ImageTransparency = 0
		otherPlayerLabelFour.ImageTransparency = 0 				
	end	
end



-- Prints out the Survivors of the game
function whoAreSurvivors() 
	print(Survivors["Survivor1"])
	print(Survivors["Survivor2"])
	print(Survivors["Survivor3"])
	print(Survivors["Survivor4"])
		
end




--[[
The main issue is in this code, it should be updating every time a player joins, it loops through the players and puts their Player into the dictionary. 

]]--
local function onPlayerAdded(child)
	
	for i, child in pairs(Players:GetChildren()) do
		for survNum,name in pairs(Survivors) do
            --Checks amount of survivors/players
			if amountOfSurvivors < 4 then
--[[
Checks to see if the Players name is already in the dictionary if it's the dictionary, it breaks out of the loop. If there's another name in the current index, it will move on to the next survivor slot
]]--
				if child.Name == name or name ~= "No One"  then

					if child.Name == tostring(name) then break
					elseif name ~= "No One" then	 
						print("Whoops")
						print("Sorry ".. child.name .. ", " .. survNum .. " is taken by " .. tostring(name) )
					end
				else
					name = game:GetService("Players"):FindFirstChild(child.name)
					print("YES")
					print(survNum .. " Is now... ".. child.name)
                    --Makes the current index equal to the Players player, not the players name
					Survivors[survNum] = game:GetService("Players"):FindFirstChild(child.name)
					print(survNum, name)
					amountOfSurvivors = amountOfSurvivors + 1
					break
					end
				end
			
		end
		
		--Sets the text of the the GUIs to the string versions of the Players player
		otherPlayerTextOne.Text = tostring(Survivors["Survivor1"])
		otherPlayerTextTwo.Text = tostring(Survivors["Survivor2"])
		otherPlayerTextThree.Text = tostring(Survivors["Survivor3"])
		otherPlayerTextFour.Text = tostring(Survivors["Survivor4"])
        --Checks to see if the Survivor slot is occupied or empty
		isOneEnabled()
		isTwoEnabled()
		isThreeEnabled()
		isFourEnabled()
		whoAreSurvivors()
			end
					
end

--Runs the function again for players already in the game	
game.Players.PlayerAdded:Connect(onPlayerAdded)
for _,child in pairs(game.Players:GetPlayers()) do
    onPlayerAdded(child)
end


I’ve tried many different onPlayerAdded functions but none seem to work for me, I’ve also looked though the dev forum and documentations to try and understand PlayerAdded more comprehensively, but I can’t seem to grasp it all that well

Any help would be greatly appreciated, I’m new to scripting so I’m sorry if the issue isn’t very complex or if you’ve seen it before, have a nice day!

4 Likes

Please try moving the Script to ServerScriptServices

4 Likes

I would suggest you using ‘for’ loop to shorten your code as well as moving the script to ServerScriptService

2 Likes

Just so you know, your current method only shows updates when the player respawns.
To do a real-time playerlist, it should be handled with a localscript.

1 Like

Try to scrap your idea and sort it out without huge scripting.
Your can use listlayout I believe to achieve a very easy and reliable playerlist.

Listlayout basicly takes all the positioning and repositiong for you.
The way I would handle a custom player list is by having a frame with a listlayout inside and everytime a player enters the game I’ll add a textlabel with the player name as the Text and as the name to that frame.
Listlayout will automaticly sort it and position it correctly so there is no need to think about that one.

If the player then leaves I’ll simply check if the frame contains a child with his name and delete that.

If you need some more help let me know but this should be enough!

2 Likes

I can now see that that is the case, thank you for pointing this out! but I’m not sure how a local script would fix this, and wouldn’t it be better to use a server script since it will display the same names in the same order for everyone’s screen and so it can’t be edited by exploiters?

@Squru @RamJoT Unfortunately this was not a quick fix, but I appreciate telling the correct place to put it into

I’m not quite sure if list layout would apply to this situation, as it is not a dynamic list (in the sense that it doesn’t grow or shrink, the 4 labels will always be there), I apologize if it’s me just being incompetent though lmao :smile:

You can always instead of doing things based on set numbers, act like youre doing it for any N players, and just use it for at most 4. In this case, it is simpler to deal with it like this. Create a gui template and change the values like the player number and such. ListLayout can be used sort them by the player number. When players leave, delete their gui and update the existing ones. Also as said before, you really should not be manipulating screen GUIs server sided.

Oh I didnt know that. I thought u want it to be dynamic.
Well then I would simply make a value inside each frame and everytime a player leaves or joins go trough the values and see if they are true or false.

So if a player is in a frame, set the frame value to true. If another player would join, it’ll loop trough all, see that the first one is true and choose the next one and set that to true. Same with leaving.

1 Like

literally every game does it in localscript. It’s meant to be a gui/display, nothing more, I don’t know why you are even mentioning exploits in this scenario.

1 Like