Is it possible to wait until a remote event's script has ended?

Hello,

I’m wondering if it’s possible to wait until a remote event’s script has ended, and then continue with the main script. The question speaks for itself. If you’d like, please look through my scripts. It should make it quite obvious what I am trying to achieve.

Note that the current delays are a bad and temporary solution.
Thank you for your help, it is appreciated.

Local script in StarterGui.

--// Variables

local RepStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Player = Players.LocalPlayer

local PlayerGui = Player.PlayerGui

local ServerTextGui = PlayerGui.ServerText
local ServerTextLabel = ServerTextGui.Frame.Text

local NPCTextGui = PlayerGui.NPCtext
local NPCTextLabel = NPCTextGui.Frame.Frame.Text

local PlayerTextGui = PlayerGui.PlayerText
local PlayerTextLabel = PlayerTextGui.Frame.Frame.Text

local TextSound = script.TextSound
local NPCText = RepStorage:WaitForChild("NPCText")
local PlayerText = RepStorage:WaitForChild("PlayerText")
local ServerText = RepStorage:WaitForChild("ServerText")

--// Functions

ServerText.OnClientEvent:Connect(function(Text)
    print("[SERVER] ServerTextEvent fired.")
    local GuiType = ServerTextGui
    local GuiText = Text
    GuiType.Frame.Visible = true
    for i = 1, #GuiText do
        ServerTextLabel.Text = string.sub(GuiText, 1, i)
        TextSound:Play()
        wait(0.05)
    end
    wait(2)
    ServerTextLabel.Text = ""
    ServerTextGui.Frame.Visible = false
end)


NPCText.OnClientEvent:Connect(function(Text)
    print("[SERVER] NPCTextEvent fired.")
    local GuiType = NPCTextGui
    local GuiText = Text
    GuiType.Frame.Visible = true
    for i = 1, #GuiText do
        NPCTextLabel.Text = string.sub(GuiText, 1, i)
        TextSound:Play()
        wait(0.05)
    end
    wait(2)
    NPCTextLabel.Text = ""
    NPCTextGui.Frame.Visible = false
end)

PlayerText.OnClientEvent:Connect(function(Text)
    print("[SERVER] PlayerTextEvent fired.")
    local GuiType = PlayerTextGui
    local GuiText = Text

    local RandomPlayer = Players:GetPlayers()
    local SelectedPlayer = math.random(1,#RandomPlayer)
    local PlayerName = RandomPlayer[SelectedPlayer]

    local ThumbnailType = Enum.ThumbnailType.HeadShot
    local ThumbnailSize = Enum.ThumbnailSize.Size420x420

    local PlayerImage, isReady = Players:GetUserThumbnailAsync(PlayerName.UserId, ThumbnailType, ThumbnailSize)
    GuiType.Frame.Player.Image = PlayerImage
    GuiType.Frame.Visible = true

    for i = 1, #GuiText do
        PlayerTextLabel.Text = string.sub(GuiText, 1, i)
        TextSound:Play()
        wait(0.05)
    end
    wait(2)
    PlayerTextLabel.Text = ""
    PlayerTextGui.Frame.Visible = false
end)

Server script in ServerScriptService.

--// Variables

local RepStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")

local NPCText = RepStorage:WaitForChild("NPCText")
local PlayerText = RepStorage:WaitForChild("PlayerText")
local ServerText = RepStorage:WaitForChild("ServerText")

local Text = ""

--//

function StartGame()

Text = "Players are loading, please wait..."
ServerText:FireAllClients(Text)
wait(5) -- Unwanted manual delay, a wait-until remote event is finished-type of function should be here instead.

Text = "Hello everyone, welcome to Clarenval Island!"
NPCText:FireAllClients(Text)
wait(5) -- Unwanted manual delay, a wait-until remote event is finished-type of function should be here instead.

Text = "I'm Nathan Eyler, your tour guide for the week!"
NPCText:FireAllClients(Text)
wait(5) -- Unwanted manual delay, a wait-until remote event is finished-type of function should be here instead.

Text = "Ugh, finally! It took such a long time!"
PlayerText:FireAllClients(Text)
wait(5) -- Unwanted manual delay, a wait-until remote event is finished-type of function should be here instead.

Text = "I'm exhausted!"
PlayerText:FireAllClients(Text)
wait(5) -- Unwanted manual delay, a wait-until remote event is finished-type of function should be here instead.

Text = "I can see that all of you are tired, don't worry; the cabins are not far away."
NPCText:FireAllClients(Text)
wait(7) -- Unwanted manual delay, a wait-until remote event is finished-type of function should be here instead.

Text = "Come with me, I'll show you the way."
NPCText:FireAllClients(Text)
wait(5) -- Unwanted manual delay, a wait-until remote event is finished-type of function should be here instead.

Text = "Follow your tour guide, Nathan. Be on the look-out for useful items!"
ServerText:FireAllClients(Text)
wait(5) -- Unwanted manual delay, a wait-until remote event is finished-type of function should be here instead.

end

wait(5)
StartGame()

I would use a remote function but you cannot use an invokeall method so i would do something like this

local plrValues = {}; -- stores if the player has finished the function or not

local function checkValues() -- function that checks if all the players have finished the function
	for _, player in pairs(game.Players:GetChildren()) do
		if plrValues[player] == false then return false end
	end
	return true
end

for _, player in pairs(game.Players:GetChildren()) do -- main loop that invokes all the clients and inits the playervalue table
 plrValues[player] = false
 spawn(function()
  remotefunction:InvokeClient(player) -- invokes the client (yields)
  plrValues[player] = true -- since the previous statement yields we set the value to true when it gets to this part because the client has finished what it needed to finished and has returned
 end)
end

repeat wait(.25) until checkValues() -- waits until all the players have finished

-- repeat and stuff

Note: i didnt rlly proof read it and stuff but its just like an outline so it doesn’t need to work

4 Likes

If I’m reading this right, doing that would make all the text be put out seemingly instantaneously. The delays are actually good, if you don’t have the delays, as soon as the client would be fired (in what you want) the next text would appear and so on. I might be misinterpreting this thread. If you are using a RemoteFunction waiting for all the clients to reply an exploiter, or just a glitched client, could modify the code to make the game not continue for anybody else.

Edit: Maybe if you use RemoteFunctions have a timeout so if a client glitches/gets modified it will continue for everyone else, like maybe 30 seconds? If you require a reply from the client, that is.

Thank you for respodning,

however; I am confused. Would you mind explaining the code for me?

Thanks.

i edited the code so hopefully u can understand it better; im not rlly good at explaining code sorry

I believe what you want is to wait for every single client to respond to your event before continuing your code. Using a remotefunction would work for a single client (until it doesn’t), but not for multiple as you would end up waiting for 1 guy to finish before starting the next.

What you should do is to simply reuse the remoteevent and then count who has responded to the event. Also, as @chasedig1 posted, you should keep some way out in case of glitched clients or hackers attempting to hijack the response.

The example code below can be used for this. (It probably doesn’t work for edge-cases like “What happens if timeout triggers at the same time someone finishes?”)

-- Localscript
-- At the end of the event listeners add this
EVENTNAME:FireServer(Text)

-- Script
local RunService = game:GetService("RunService") -- Using this service to make a timeout
local Players = game:GetService("Players")

local Finished = Instance.new("BindableEvent") -- This is the event that tells you that everything is done.

-- Function Usage: SendMessageToAllPlayers(ServerText/NPCText/PlayerText, Text_To_Display, Timeout (seconds))
local function SendMessageToAllPlayers(event, message, timeout)
	local Waiting = {}
	
	for _, p in next, Players:GetChildren() do -- next, Table is effectively pairs(Table).
		Waiting[p.Name] = true
	end
	
	local Wait, Heart
	local t = RunService.Stepped:Wait()
	
	Wait = event.OnServerEvent:Connect(function(player, response)
		if response == message then -- Check if this is actually responding to the message sent (in case of timeout troubles.)
			Waiting[player.Name] = false
			print(player.Name .. " Responded")
		
			for _, w in next, Waiting do
				if w then return end -- Someone is still waiting, don't do anything.
			end
			-- Passed the check tell the server it's finished
			print("Everyone responded")
			Finished:Fire()
			Heart:Disconnect()
			Wait:Disconnect() -- Disconnect the event listener (don't need it anymore for this message)
		end
	end)
	
	Heart = RunService.Stepped:Connect(function(d)
		if (d-t) >= timeout then -- If time is more than timeout, stop the wait and declare finished. (Unlucky for players who are not finished...)
			print("Timeout")
			Finished:Fire()
			Wait:Disconnect()
			Heart:Disconnect()
		end
	end)
	
	event:FireAllClients(message)
end

function StartGame()
Text = "Players are loading, please wait..."
SendMessageToAllPlayers(ServerText, Text, 5) -- (Event, Text, Timeout)
Finished.Event:Wait() -- Wait for finished to fire (either by timeout or everyone responded)

Text = "Hello everyone, welcome to Clarenval Island!"
SendMessageToAllPlayers(NPCText, Text, 5)
Finished.Event:Wait()
-- Continue...
1 Like