PlayerAdded/PlayerRemoving should fire for local scripts too

Use case:

I need to maintain status symbols over players’ heads:

To do this, I use a localscript in PlayerScripts to upkeep the synced rotation, offset, and transparency of all symbols and use RenderStepped to move the emblems above characters’ heads. I sort the emblems based on players:

statusList = { [player1] = { currentSymbol = 2; statusEffects = { {Name="Muted", Symbol=Object}; {Name="Frozen", Symbol=Object}; {Name="Poisoned", Symbol=Object}; {Name="Burning", Symbol=Object}; }; }; [player2] = { currentSymbol = 4; statusEffects = { {Name="Muted", Symbol=Object}; {Name="Frozen", Symbol=Object}; {Name="Poisoned", Symbol=Object}; {Name="Burning", Symbol=Object}; {Name="Paralyzed", Symbol=Object}; }; }; }

Which means I need to create an entry in statusList for each player each time one joins the game. Even though this can be resolved with metatables and __index, I don’t see a particular reason why PlayerAdded and PlayerRemoving are disabled on the client in the first place.

1 Like

Current PlayerAdded/PlayerRemoving events do fire in local scripts but that’s only for the local player. It won’t fire for other players, which I don’t see why not.

You could just use ChildAdded/ChildRemoved for this instead which do fire in local scripts.

game.Players.ChildAdded:connect(function(player)
	if (player:IsA("Player")) then
		-- do stuff
	end
end)
1 Like

But… it should work… and not require the workaround… like why not have it work?

oxcool wasn’t saying that it shouldn’t be fixed – he was being realistic and giving a solution that can be used until ROBLOX fixes this who knows when.

Like what Echo said. I’m not against having PlayerAdded/PlayerRemoving events work for other players as well. But for now you could use the alternative solution as it works just fine.

Not disabled. PlayerAdded and PlayerRemoving fire as the result of a client connecting to or disconnecting from the server. It wouldn’t make sense for them to fire on clients, because clients don’t connect to clients. The only way a client can be made aware of Player objects is if they are replicated from the server. So, the correct way to detect them on a client is to use ChildAdded and ChildRemoving, which fire after objects are replicated.

Regardless of what goes on behind the scenes, the naming of PlayerAdded and PlayerRemoving imply that they fire whenever a player is added or when a player is removing – not explicitly when it connects or disconnects from the server. They’re not named PlayerConnected and PlayerDisconnected. Their function should be what their name implies – why should I have to hook up ChildAdded and use an extra if statement to check if a player was added to the game? That’s what PlayerAdded tells me it’s supposed to do based off of its name, but it doesn’t.

Why does :GetTouchingParts() have the word “Touching” in it when it only gets intersecting parts. It should be :GetIntersectingParts()

I dunno man. The API is weird.

I’m implying that Echo is right considering the API has bad naming in multiple areas.

Just because something is does not mean that something should be.

You have it backwards. Their names should be what their function implies, not the other way around. I agree that the names aren’t as great as they could be. But keep in mind that you’re talking about one of the oldest bits of the API. The names would have been considered perfectly acceptable back then, because scripting was much more simple. Unfortunately, Roblox engineers can’t predict the future, and they can’t make backwards-incompatible changes, so we’re stuck with what we have. The only thing that can be done is to document with detail. Maybe.

Let’s say an engineer decides to implement PlayerAdded/Removing on the client. This new implementation is basically a shortcut for using ChildAdded/Removing, including a check for whether the child is a Player. The original implementation would now have to check if it’s running on a server, to make sure it doesn’t fire these events if it’s on a client. The new implementation, likewise, would have to make sure it doesn’t fire the events unless it’s on a client.

But there is an issue with this. An instance can be both a server and a client (see Play Solo). In this case, which implementation gets priority? Server scripts expect the server implementation, and client scripts expect the client implementation, but both sets of scripts are running in the same environment. The problem lies in the fact that you have two different implementations firing the same events. This can be solved in a few ways:

  1. Pick one implementation over the other. The problem here is what happens if the behaviors of the two implementations diverge.
  2. Add a new set of events to be fired by the new implementation. The problem with this is that it’s redundant in multiple ways.
  3. Change the original implementation (fire on client connect/disconnect) to be the new implementation (fire on Player added/removing). The problem here is that it’s potentially a backwards-incompatible change.

The last option is the most promising. Currently, the apparent behaviors of the original and new implementations match pretty much exactly (even though this wasn’t the case in the past). In theory, making the change shouldn’t have any impact. As a bonus, if necessary, new events with proper names can be added, which are fired by the original implementation (PlayerConnected/Disconnecting).