Would it be possible for a Player to join before this code executes? If that were the case, how would you avoid that? I am currently using one script architecture with Module loading and I have Server Scripts with a PlayerAdded event listener, and I am worried if a case like this were to happen.
What about modules? Like I said I’m using a one script architecture where I have one server script that loads a bunch of modules. One of those modules is called a “Data” script. Inside of this contains a playeradded event.
Module Scripts are there too, so long as it isn’t parented to a running local script.
Normally what happens is that the Server already has it’s contents there and it’s loaded. When a player is added, then the player actually downloads (replicates) information from the server.
Alright but what if I’m loading modules and the Data Module is the last one to load, and players have already joined before the Data module has loaded? What do you do then?
In most cases I’ve had server scripts run before the player joins. As long as you don’t yield you shouldn’t need to worry about this happening but if you’re still worried, this is something you can use to make sure
local Players = game:GetService("Players")
function PlayerSetup(player)
-- insert code you would usually put in playeradded here
end
for _, player in pairs(Players:GetPlayers()) do
PlayerSetup(player)
end
Players.PlayerAdded:Connect(PlayerSetup)
EDIT: The code above is fine if you don’t have anything in PlayerSetup that yields, but if the code you’re putting in PlayerSetup yields please see this reply
The server will only accept players after all scripts yield. Roblox Lua runs on one thread so all queued tasks will finish before a player event is triggered on the Lua side.
So in conclusion, any Server Scripts that run and any Server Scripts that require modules will all run before the Player joins the server no matter what? I’m mainly concerned by this because I have a Data Module which will do certain things with the Player’s Data once a Player joins.
yes as long as the module does not include a yield. Im guessing at the issue being related to a datastore call as it is a yield function (GetAsyn / SetAsyn ect).
A very long time ago I used to use a weird method of making sure all of the places in my game had the same code and instances required to run the game before packages were added to Roblox (there may have been better methods that I didn’t know of at the time though…) It was a script placed in all the places and it used InsertService to insert a model that would contain all game data which would then move all of the instances to the correct places they should be in. I ran into an issue where the first player to join the server were being placed in before InsertService was done downloading the model which meant PlayerAdded was being fired before the scripts were ready so I had to use code similar to the one I wrote there so it wouldn’t be a problem anymore
LexiDog5’s answer is the correct and standard way to approach this issue. You should always handle player added functions in this way. OP should mark it as the solution so the rest of the replies don’t confuse anyone else with the same question.
There is a caveat to this solution that should be kept in mind. If PlayerSetup never yields, then the code is correct. However, if yielding is possible, then some minor adjustments should be made:
local Players = game:GetService("Players")
function PlayerSetup(player)
-- insert code you would usually put in playeradded here
end
-- Connect the listener *first*.
Players.PlayerAdded:Connect(PlayerSetup)
for _, player in pairs(Players:GetPlayers()) do
-- Run setup in a coroutine (use preferred spawning method).
coroutine.wrap(PlayerSetup)(player)
end
-- More code can safely be added here.
In this particular case, connecting the listener first isn’t necessary, but it’s good practice anyway.