Skip to content

Functions

Functions are Red's version of RemoteFunctions. If you don't know what they are, it's a way to call code on the server from the client and get return values. Red only allows clients to call the server, not the server to call clients.

Declaring

Functions are declared similarly to events, they take two validation callbacks: one for the arguments and one for the return value.

lua
local Red = require(Path.To.Red)

return Red.Function("FunctionName", function(Arg1, Arg2, Arg3)
	assert(type(Arg1) == "string")
	assert(type(Arg2) == "number")
	assert(type(Arg3) == "boolean")

	return Arg1, Arg2, Arg3
end, function(Ret1, Ret2, Ret3)
	assert(type(Ret1) == "string")
	assert(type(Ret2) == "number")
	assert(type(Ret3) == "boolean")

	return Ret1, Ret2, Ret3
end)
local Red = require(Path.To.Red)

return Red.Function("FunctionName", function(Arg1, Arg2, Arg3)
	assert(type(Arg1) == "string")
	assert(type(Arg2) == "number")
	assert(type(Arg3) == "boolean")

	return Arg1, Arg2, Arg3
end, function(Ret1, Ret2, Ret3)
	assert(type(Ret1) == "string")
	assert(type(Ret2) == "number")
	assert(type(Ret3) == "boolean")

	return Ret1, Ret2, Ret3
end)

These callbacks must follow the same three rules that event validation callbacks do:

  1. The callback returns the arguments in the same order they were passed in.
  2. The callback must error if the arguments are invalid.
  3. The callback must narrow the types of the arguments.

These callbacks are only called in specific circumstances. Do not use these callbacks as middleware, logging, or other side effects.

TIP

I once again suggest using Guard to both narrow and check types at the same time.

lua
local Red = require(Path.To.Red)
local Guard = require(Path.To.Guard)

local CheckArg1 = Guard.Map(Guard.String, Guard.Number)
local CheckArg2 = Guard.List(Guard.Vector3)
local CheckArg3 = Guard.Boolean

local CheckRet1 = Guard.String
local CheckRet2 = Guard.Number
local CheckRet3 = Guard.Set(Guard.String)

return Red.Function("FunctionName", function(Arg1, Arg2, Arg3)
	return CheckArg1(Arg1), CheckArg2(Arg2), CheckArg3(Arg3)
end, function(Ret1, Ret2, Ret3)
	return CheckRet1(Ret1), CheckRet2(Ret2), CheckRet3(Ret3)
end)
local Red = require(Path.To.Red)
local Guard = require(Path.To.Guard)

local CheckArg1 = Guard.Map(Guard.String, Guard.Number)
local CheckArg2 = Guard.List(Guard.Vector3)
local CheckArg3 = Guard.Boolean

local CheckRet1 = Guard.String
local CheckRet2 = Guard.Number
local CheckRet3 = Guard.Set(Guard.String)

return Red.Function("FunctionName", function(Arg1, Arg2, Arg3)
	return CheckArg1(Arg1), CheckArg2(Arg2), CheckArg3(Arg3)
end, function(Ret1, Ret2, Ret3)
	return CheckRet1(Ret1), CheckRet2(Ret2), CheckRet3(Ret3)
end)

Setting the Callback

A singular callback must be set on the server to allow clients to call the function. This callback is given the arguments and must return the expected return values. This callback may only be set on the server, attempting to set it on the client will result in an error.

lua
local Function = require(Path.To.Function)

Function:SetCallback(function(Player, Arg1, Arg2, Arg3)
	return Arg1, Arg2, Arg3
end)
local Function = require(Path.To.Function)

Function:SetCallback(function(Player, Arg1, Arg2, Arg3)
	return Arg1, Arg2, Arg3
end)

Calling

Functions can only be called from the client. The client must pass valid arguments to the function, and will be given back a Future that completes with the returned values.

It also returns a success boolean, similar to pcall, which is false if the server's callback function errored, and true if it was successful.

lua
local Function = require(Path.To.Function)

local Success, Ret1, Ret2, Ret3 = Function:Call("Hello", 1, true):Await()
local Function = require(Path.To.Function)

local Success, Ret1, Ret2, Ret3 = Function:Call("Hello", 1, true):Await()