Player Players:WaitForLocalPlayer()

“It’s possible to make this yourself” isn’t what I meant. The full implementations of GetDescendants, WaitForChild, and FindFirstChild are non-trivial. They are very general functions that could appear all over the place, and whose results may differ with each call.

Meanwhile, WaitForLocalPlayer can be expressed in four lines, as demonstrated. It detects a single value, which remains constant once it has been acquired. It’s too focused, its most complex part occurs exactly once, and it isn’t applicable to all contexts (servers).

A more arguable approach to your problem might be a general function that waits until a given property meets a given condition. WaitForLocalPlayer might be implemented like so:

localPlayer = Players:WaitForProperty("LocalPlayer", Enum.Condition.NotEqual, nil)

Here, you can make the argument that it benefits many cases where a developer needs to wait for a property to be a certain value. LocalPlayer would be just one example.

4 Likes

The problem is we don’t always know whether there will be a player or not.

Is that not solvable by some combination of IsServer, IsClient, and IsStudio?

Nope. Both IsClient and IsServer are true in Play Solo.

Or it could just error if you call it on a server

IsServer and not IsClient    Server
IsClient and not IsServer    Client
IsServer and IsClient        Play Solo/Hybrid

Seems pretty straight forward.

5 Likes

I want to know whether or not the module is being called by a server or client script in play solo to emulate online behavior. If I don’t, I either have to

  • Spin up a test server and player (slow!) repeatedly whenever I test
  • Wait for errors to appear online because they didn’t appear in play solo

That Hybrid scenario is what I’ve found to be the problem. It would be nice to still explicitly know whether it’s running on a LocalScript or Script for the sake of testing in Solo. (But perhaps there could be arguments made about design principle & proper testing environments for us as developers)

Like @Osyris said, it seems like there may be a deeper problem if they hybrid problem of Play Solo is causing problems. If you’re loading a module script that requires the LocalPlayer, why would a server-side Script ever be requiring it?

Maybe you should split it into a shared Utils library and a ClientUtils library?

This doesn’t seem like an issue of Roblox needing a new method, this seems like a strange dependency upon behavior that changes the entire behavior of a script, which is ambiguous to say the least.

1 Like

It’s an example. You don’t solve the problem by solving the example.

Because there are shared utilities. E.g. printTable shouldn’t be two separate modules on the server and client. An example that involves client/server is my object framework. It’s mostly server/client-independent, but there’s a slight difference between the two where indices and values are reversed in a dict so they can do lookups based on what the other one sends.

I disagree. My solving of that problem solves this paradigm as a whole. I can’t see an example where a script that is required by a server-side Script should ever change its behavior if required by a LocalScript. That is simply a shaky paradigm and I don’t see a reason for that to be followed.

1 Like

That’s what the shared utils code is for. Anything client-specific could use a Client Utils library. There’s no reason a single LocalScript/ModuleScript can’t require both.

The second example is shared but needs to differentiate.

…Why not have something like this?

local RunService = game:GetService("RunService")
if RunService:IsServer() then
    module.ServerData = --server data
end
if RunService:IsClient() then
    module.ClientData = --client data
end

The client and server can use two different lookups. In the case of a normal server, only one of those two tables will ever be populated. In the case of Play Solo, both will be populated.

The general paradigm that seems to be the source of this problem is that the server and client are using the same thing, with the same name, but expecting different behavior, which is ambiguous and I’d argue a bigger problem.

1 Like

That will not work because Play Solo has both. I want to discover errors in Play Solo (e.g. accidentally using the client functionality in a server script) and not in a live game server.

1 Like

That’s what Start Server/Start Player is for…? I don’t think I understand that last comment properly, sorry.

1 Like

That’s not the proposal. The proposal is that it behaves differently whether there is a localplayer or not, and in order to behave properly it needs to wait until it knows for sure whether there is one or not.

A shared module can’t explicitly determine if it’s ran by a LocalScript or a Script because all the tricks to figure this out fail in Play Solo (i.e. they all appear to be client side, which is technically true but not helpful for testing.)