BindToClose Soft Shutdown not working with multiple players

Hi All,

Let me preface this by saying sorry that I’ll be putting a lot of code in here, I’m honestly not too sure where it’s gone wrong, and I believe it’s just a couple of sneaky lines in here causing the problem.

Basically, I’m making a ‘Soft Shutdown’ script, where players are sent to a temporary lobby, and rejoin later to an updated server, pretty standard stuff. Here are the materials I’ve been referring to whilst creating this:

However, despite following these two sources very closely, and only introducing negligible change to work with my own data modules, the mechanic completely breaks upon shutting down servers with more than one player inside. Here’s the code which I believe contains the problem.

elseif RunService:IsStudio() == false then
	game:BindToClose(function()
		if not Players:GetPlayers()[1] then return end
		
		local ReservedServerCode = TeleportService:ReserveServer(game.PlaceId)
		
		local MainThread = coroutine.running()
		local NumThreadsRunning = 0

		local ServePlayer = coroutine.wrap(function(Player, Args)
			local UserId = Player.UserId
			
			ReplicatedStorage.Communication.RemoteEvents.ShutdownMsg:FireClient(Player)
			if Args.ShouldSave then
				if UserId ~= nil and Args.SavingData ~= nil then
					if not CRUD.new("UPDATE", UserId, Session.getDataSafeSaving(Player.UserId)) then
						warn(string.format("Failed to save %d's data", UserId))
					end
				end
			end
			
			TeleportService:TeleportToPrivateServer(game.PlaceId, ReservedServerCode, {Player})
			
			NumThreadsRunning -= 1

			if NumThreadsRunning == 0 then
				coroutine.resume(MainThread)
			end
		end)
		
		Players.PlayerAdded:Connect(function(Player)
			NumThreadsRunning += 1
			ServePlayer(Player, {ShouldSave = false})
		end)

		for _, Player in ipairs(Players:GetPlayers()) do
			NumThreadsRunning += 1
			ServePlayer(Player, {
				ShouldSave = Session.shouldSave(Player.UserId),
				SavingData = Session.get(Player.UserId).Saving
			})
		end

		if NumThreadsRunning > 0 then
			coroutine.yield()
		end
		
		while Players:GetPlayers()[1] do
			task.wait(1)
		end
	end)
end

Ideally, each player would, in turn, be shown a shutdown message e.g. ‘Server is shutting down, you will rejoin automatically’, invoked by ‘ShutdownMsg:FireClient(Player)’, then would teleport to a temporary lobby, etc… However, in practice, only one player will be shown this shutdown message, and immediately after, every player in game will be prompted with ROBLOX’s default shutdown message without being teleported, as if the BindToClose function has completed, which it hasn’t.

I’m honestly not too sure why this is happening, any help is much appreciated, thanks :slight_smile:

It appears the issue was to do with calling the ServePlayer coroutine multiple times, for some reason it would skip to the end of the coroutine of the first player instead of calling it for the second player, which I suppose makes sense in terms of standard coroutine behaviour, but it directly contrasts with the BindToClose documentation saying this sort of method should work.

If anyone is having a similar problem, I’ve altered my code to have ServePlayer as a standard function, then every time it is called, it’s called as a new thread.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.