Bug in Allies System

So hello its me Sam again
Today iam trying to make an allies system
I made most of them but there some bug there

Photos

As you can see in the picture
my account doesnt show my alt invite Button when he joined
But my alt does it
And my account joined before the alt

So the issue is the player who joined the game cant load the player joined after it
But the player joined after it can load all the player joined before but cant load all player after it also

So what cause this error ?
Here is the PlayerAddedScript so far

Any help is appriciated Thanks for reading
For more information you can ask below !

local Slot = game.ReplicatedStorage.Slot
local players = game:GetService("Players")

local function onPlayerRemoving(player)
	for i, child in pairs(game.StarterGui.AlliesGui.Frame.NeutralScrolling:GetChildren()) do 
		if child.Name == player.Name then
			child:Destroy()
		end
	end
end

local function onPlayerAdded(player)
	local Allies = Instance.new("Folder")
	Allies.Parent = player
	Allies.Name = "Allies"
	
	local newSlot = Slot:Clone()
	newSlot.Parent = game.StarterGui.AlliesGui.Frame.NeutralScrolling
	newSlot.Name = player.Name
	newSlot.Text = player.Name
end

players.PlayerAdded:Connect(onPlayerAdded)
players.PlayerRemoving:Connect(onPlayerRemoving)

The problem is that the startergui has already been duplicated by the time you add the slot to it, and what you should be doing is putting it into the “PlayerGui”, which is located in the player before “onPlayerAdded” invokes

local Slot = game.ReplicatedStorage.Slot
local players = game:GetService("Players")

local function onPlayerRemoving(player)
	for i, child in pairs(game.StarterGui.AlliesGui.Frame.NeutralScrolling:GetChildren()) do 
		if child.Name == player.Name then
			child:Destroy()
		end
	end
end

local function onPlayerAdded(player)
	local Allies = Instance.new("Folder")
	Allies.Parent = player
	Allies.Name = "Allies"
	
	local newSlot = Slot:Clone()

	--//Changed Below
	newSlot.Parent = player.PlayerGui:WaitForChild('AlliesGui'):WaitForChild('Frame'):WaitForChild('NeutralScrolling')
	--//Changed Above

	newSlot.Name = player.Name
	newSlot.Text = player.Name
end

players.PlayerAdded:Connect(onPlayerAdded)
players.PlayerRemoving:Connect(onPlayerRemoving)
1 Like

The reason is probably because that you’re not updating the PlayerGui of the previous players, in your onPlayerAdded function you’re generating a new slot and adding it to “startergui” by adding it to startergui won’t update a player’s current PlayerGui, I believe it’ll only update if they reset and refresh their UI, so you’ll have to access the “playergui” of the previous players and update them also

But how can i Update the PlayerGui for every player in game once a player joined ?
:thinking:

RemoteEvent:FireAllClients shall work ?

local PlayerGui = Player:WaitForChild("PlayerGui")

I believe this is a local script right? If so, then you will have to get the PlayerGui of the Player first, then instead of referring to the “StarterGui”, refer to the PlayerGui, so replace “game.StarterGui” with “PlayerGui” (or however your variable is spelt that refers to the PlayerGui

newSlot.Parent = player:WaitForChild('PlayerGui'):WaitForChild('AlliesGui'):WaitForChild('Frame'):WaitForChild('NeutralScrolling')

this code will work but

the ‘player’ is already defined as the player who was just joined
So every player else in the game doesnt get that button to send allies request to him hm

for i, desc in pairs(players:GetDescendants()) do 
		if desc.Name == "NeutralScrolling" then 	
			newSlot.Parent = desc
		    newSlot.Name = player.Name	
		    newSlot.Text = player.Name
		end
	end

So i make a loop inside the game.Players*

It will get the Neutral scrolling of every player in Players
and add the slot in all of it 
But will this work ? since i only cloned one but give to all of them?
--SERVER
local Players = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")
local RE = RS:WaitForChild("RemoteEvent")

Players.PlayerAdded:Connect(function(Player) --new player joined
	RE:FireAllClients() --fire all the clients each time a new player joins so that the gui is modified for each player locally
end)

--LOCAL
local RS = game:GetService("ReplicatedStorage")
local RE = RS:WaitForChild("RemoteEvent")
local Player = game.Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")
--add more references to instances inside the playergui folder here

RE.OnClientEvent:Connect(function()
	--modify the player's playergui contents here
end)

This is just an example but I’ve added comments which should make it easy to follow.

local Players = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")
local JoinedRemote = RS:WaitForChild("JoinedRemote")
local LeftRemote = RS:WaitForChild("LeftRemote")

local function onPlayerAdded(player)
	local Allies = Instance.new("Folder")
	Allies.Parent = player
	Allies.Name = "Allies"
	JoinedRemote:FireAllClients() --have a local script handle gui manipulation
end

local function onPlayerRemoving(player)
	local labels = player.PlayerGui.AlliesGui.Frame.NeutralScrolling:GetChildren()
	if labels then
		for _, label in ipairs(labels) do
			if label.Name == player.Name then
				LeftRemote:FireAllClients() --have a local script handle gui manipulation
			end
		end
	end
end

Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)

The same concepts applied to your original script.

Yeah yeah my script i jsut made somehow similar to this now lol

But you know what its opposite now

The player who joined before can get all the player which is fine now
but the player joined after only got his name
he cant get the player joined before name lol

How to fix that ?

To clarify the player who joined before gets the player who joined after but not vice versa?

what do you mean ? iam confused lol

I was confused by your original post, try and rewrite it please.

local Players = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")
local Slot = RS:WaitForChild("Slot")

local function onPlayerAdded(player)
	local Allies = Instance.new("Folder")
	Allies.Parent = player
	Allies.Name = "Allies"
	for _, Player in ipairs(Players:GetPlayers()) do
		local scrollingFrame = Player.PlayerGui.AlliesGui.Frame.NeutralScrolling
		if scrollingFrame then
			local newSlot = Slot:Clone()
			newSlot.Name = player.Name
			newSlot.Text = player.Name
		end
	end
end

local function onPlayerRemoving(player)
	for _, Player in ipairs(Players:GetPlayers()) do
		local Labels = Player.PlayerGui.AlliesGui.Frame.NeutralScrolling:GetChildren()
		if Labels then
			for _, Label in ipairs(Labels) do
				if Label.Name == player.Name then
					Label:Destroy()
				end
			end
		end
	end
end

Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)

This is an implementation without the use of remote events.

why do you use in ipairs ? thought it should in pairs ?

The pairs iterator function is required to iterate over the items of a dictionary, for arrays ipairs/pairs can both be used. As the ipairs iterator function is more efficient I opted to use it instead. If you don’t know the difference then it’s safe to stick with using pairs only.