local ChosenPlayers = ChoosePlayers:InvokeClient(Sensei, Settings.ACTIVE_PLAYERS)
if #ChosenPlayers == 2 then
print('Players have been chosen')
else
print('Player did not pick')
end
Basically I get a selected player to pick 2 players, so I fire a RemoteFunction and wait for the response from said player. However if that player leaves, that causes entire game to stop. How can I have like a way of checking if the RemoteFunction hasn’t be returned?
I need to wait for a returned value one way or another.
RemoteFunction works better than RemoteEvent, as then I’d have to do this
local ChosenPlayers = ChoosePlayers:FireClient(Sensei, Settings.ACTIVE_PLAYERS)
ChoosePlayers.OnServerEvent:Wait()
if #ChosenPlayers == 2 then
print('Players have been chosen')
else
print('Player did not pick')
end
You have made a mistake. All :Fire methods don’t return anything (or in C++ terms like Roblox uses, void). Thus ChosenPlayers is nil.
The way you would do it is the client would through a :FireServer call send the data. And from there you validate it. Don’t wait for the response, because
As said before, exploiter can choose to not return anything
Exploiter can send bad info (through :FireServer they can as well, but validating through OnServerEvent listener would be very easy
Exploiter can wait(n) before returning, thus making server yield even longer. (i think, if not correct me)
But in what context is the client giving data to the server. Is it like through a GUI or how do you do it.
function remotef.OnClientInvoke(...)
return 5
end
-- am eval xploytr wach awt 4 mi!!11
function remotef.OnClientInvoke(...)
while true do
-- nothing!
wait(n)
end
end
If I were you I would put the :Invoke call into a coroutine. Then, after the coroutine has started executing, I’d put this:
local timeWaiting = 0
repeat
wait(1)
timeWaiting = timeWaiting + 1
until gotAnswer or timeWaiting > 3.
gotAnswer would be the result of the Invoke. timeWaiting would be an integer that you increase by 1 inside the loop. You could change 3 to how long you want to wait for the player to choose. Then,once you’re outside of the loop, check if gotAnswer is nil. If it is, get a different player to choose or handle it however you see fit.
They can and do have uses. OnClientInvoke/InvokeClient are the ones to be careful with. In fact, client invokes are so unsecure you’re better off not using them.
While there’s truth to what you’re saying, I don’t think I would consider it the one and only solution to the problem.
I can’t say I fully understand your hatred for RemoteFunctions and InvokeServer. They are used widely across several major titles on the site and have no negative when used correctly.
ChoosePlayers:FireClient(Sensei, Settings.ACTIVE_PLAYERS)
ChoosePlayers.OnServerEvent:Connect(function(chosenPlayers)
if #chosenPlayers == 2 then
else
end
end
As exploiter could once again just not fire the event back?
No not really, since roblox doesn’t have like a timeout argument for :Wait for events (maybe not yet), this is what we can use for now.
Oh and I modernized this because I actually needed to use it, if you want here is the code
Timeout for event
local function wait_until_timeout(event, timeout)
if type(timeout) == "number" then
local signal = Instance.new("BindableEvent")
local connection
connection = event:Connect(function(...)
connection:Disconnect()
signal:Fire(...)
end)
delay(timeout, function()
if connection then
connection:Disconnect()
connection = nil
signal:Fire()
end
end)
return signal.Event:Wait()
end
return nil
end
You can make it into a module script so you can use it anywhere in any script.