Player Players:WaitForLocalPlayer()

And what if the game has yielded at all before requiring a module? Then LocalPlayer will be set. I’d appreciate it if you were open to learning about our needs for this instead of trying to shove that something you’ve never experienced is unimportant down our throats.

Yes, WaitForLocalPlayer would no accomplish anything. The original suggestion needs to be improved, but the need is still there.

How is the need there? You keep saying I should be open to learning and that I just have had the fortune of never needing this, but I really don’t see how this would ever help. The reason I continue to persist is because no one has given a good example of how a need for this isn’t a symptom of another problem.

I don’t want it to work in both during Play Solo. I want it to error so if I accidentally call a client function from the server, I know about it immediately.

I’ve posted multiple times why it is necessary. The reason you don’t see how it would help is because you’ve dug your feet in.

No, that’s not why. I’m very open to seeing how this could help. But you haven’t posted an example that shows why it is necessary. You’ve posted examples of where a small refactor could fix everything, and is arguably the better model.

It is not possible to distinguish local scripts and scripts (without the getfenv hack) in Play Solo – I repeat, again. Please explain to me how this is not the case. LocalPlayer is set in server scripts in Play Solo – even if it is not set at the very beginning, some modules are required mid-game when it’s already set.

I can see how a less hacky way of knowing whether you’re in a client side or server side execution environment can help, I suppose. But I don’t see how WaitForLocalPlayer helps, and I still believe any shared modules should be 100% environment independent.

2 Likes

But it doesn’t mean it does exist, either.

Multiple people have told you they’ve encountered this in their own projects… And these aren’t newbs either – these are interns and people who have been programming for ages. I promise you we’re not idiots – if there was a better way, we wouldn’t be posting here.

I’m an intern, I consider myself not too much of an idiot, and yet I find myself always learning new and better ways of doing things from the people on this forum. I’ve been called out on this forum, stackoverflow, and other places, for making stupid mistakes and I am better for it.

I’m not saying none of you know what you’re doing. I’m just saying the above idea posted in this thread doesn’t sound like a solution - it sounds like there might be a different problem that should be addressed.

2 Likes

Yes, you’ve come around to the real problem. The problem is that the script environment in Play Solo is different from that of the server testing environment and the production environment in a fundamental way. This isn’t great, testing environments should mirror production as much as possible. The fact that it’s hard for scripts to detect and adjust for the Play Solo difference is just a symptom of this problem.

Given that the difference does exist and that it’s probably not something we’ll be able to address anytime soon it doesn’t seem like an unreasonable request to provide an easy way to detect and adjust for it.

4 Likes

Sounds to me like we need something (maybe as an option) that allows modulescripts to not only be required per identity, but also per serverscript/localscript:

-- Module
return math.random()
-- Script
require(module) --> 123
-- LocalScript
require(module) --> 456
-- Script
require(module) --> 123
-- LocalScript
require(module) --> 456

require() is internally already aware about which thread called it, as depending on the identity, the modulescript needs to run “differently”. (Both identity 0 and 2 will have different modulescript versions, so the division is made by the identity, not the VM/context) It wouldn’t be farfetched to mark threads spawned by a Script as “Server” and other scripts as “Client”, which results in a different version of the modulescript.

Note: the mark would be inherited by spawn()/delay()/coroutine.something()ed threads, like the identity

Note: I said all non-Script scripts would be marked Client, which include CoreScripts. Only problem would be for serverside CoreScripts, but when they’re loaded, the threads could still be marked as Server if that matters

While you mark threads that way, you might as well add a quick check to .LocalPlayer that basically does Server? return nil anyway. Could also reflect that property in IsClient/IsServer, so it just reads the thread “type”. (but adding :IsHybrid() or :IsPlaySolo() so we know we are running in a mixed environment (for e.g. physics) would be nice)

I’m pretty sure identity 0 and 2 have different modulescript versions, but what about 2 and 3? just curious

I considered this, but then concluded that it was a misuse of identities. The initialize-once-per-identity behavior of modules is meant to ensure that information isn’t shared insecurely between identities. We’re trying to separate Scripts from LocalScripts for reasons other than security, so I’d say it’s out of scope.

Since play solo can’t accurately represent a real game anyway, I think the better solution would be to ignore it entirely, and focus on improving the speed of test servers and studio startup time in general.

6 Likes

Surely 99% of the time, the local player is always there because it’s a local script?

local player
while true do --breaks
  player = game.Players.LocalPlayer
  if player then break else wait() end
end
local char = player.Character or player.CharacterAdded:wait()

:+1:

1 Like

I do this because I’m an evil off breed of satan

2 Likes

For a moment I was thinking “pretty sure it doesn’t work, you can’t figure out who called require() that way, cuz separate thread”, but then it clicked Anaminus probably meant to use it in methods/etc returned by the modulescript