Networking
A module used to simplify client-server communication
Important Note
While the networking module allows you to have typed events, it DOES NOT CHECK THE INPUT! We recommend using a library like Roblox's t to insert runtime checks!
Networking in Roblox can be an annoying process, especially if you have to wire it all together yourself. That's why Quebec has a feature-rich networking library.
Events
The networking library supports two kinds of events: typed and untyped events. Untyped events essentially accept every argument while typed events have strict types for the arguments. Here's an example:
local Networking = require(script.Parent.Quebec.modules.Networking)
-- calling :client() on the event will return the client-sided executor.
-- it was added to improve autocompletions and a way to share events without declaring
-- them multiple times. refer to "Organizing"
local Untyped = Networking.event("Equipitem"):client()
Untyped:fire("Sword", 1, 2, 3) -- this works, as it accepts every argument
Untyped:connect(function (...: any)
print(...) -- prints args
end)
-- note: the parenthesis around the "string, number" are cosmetic in this case
-- but are good practice to group type packs.
local Typed: Networking.Event<(string, number)> = Networking.event("DropItem")
local TypedExecutor = Typed:client()
TypedExecutor:connect(function (item: string, amount: number)
print("dropping", tostring(amount), "x", item)
end)
TypedExecutor:fire("Sword", 1) -- works
TypedExecutor:fire("Sword", false) -- this would show a warning due to type mismatch
Please remember that Quebec does NOT perform runtime type checks.
Functions
The library also supports RemoteFunctions. Just like the events, there are typed and untyped ones. However, this time the parentheses aren't optional. Let me show you:
local Networking = require(script.Parent.Quebec.modules.Networking)
-- calling :client() on the function will return the client-sided executor.
-- it was added to improve autocompletions and a way to share events without declaring
-- them multiple times. refer to "Organizing"
local Untyped = Networking.func("EquipItem"):client()
-- you can connect to the function like so:
Untyped:connect(function (...: any): ...any
return 1, 2, 3
end)
local success = Untyped:fire("Sword", 1, 2, 3) -- accepts any, returns any
local success, a, b, c = Untyped:fire() -- this would work aswell
type Args = (string, number)
type Returns = boolean
local Typed: Networking.Func<Args, Returns> = Networking.func("DropItem")
-- we call this separately for simplicity
local TypedExecutor = Typed:client()
TypedExecutor:connect(function (a0: string, a1: boolean): boolean
print(a0, a1)
return true
end)
local success = TypedExecutor:fire("Sword", 1) -- works. the type of "success" is now boolean
-- technically, you could also use inline types:
local Typed2: Networking.Func<(string, string), (number, number)> =
Networking.func("CountWords")
local Typed2Executor = Typed2:client()
local wordCountA, wordCountB = Typed2Executor:fire("hello world", "does this count")
Typed2Executor:connect(function (word1: string, word2: string)
return 1, 2 -- pseudo returns
end)
-- any type mismatch would show a warning again
Organizing
We recommend to create an Events
ModuleScript somewhere in ReplicatedStorage
where you save all your events so both the server and client can access the same events:
local Networking = require(script.Parent.Quebec.modules.Networking)
return {
EquipItem = Networking.event("EquipItem") :: Networking.Event<string, number>,
DropItem = Networking.event("DropItem"),
-- you can also put functions here, or create a seperate "Functions" ModuleScript
BuyItem = Networking.func("BuyItem") :: Networking.Func<(string), (boolean, number)>,
GetItemData = Networking.func("GetItemData"),
}
You can then access any executor like this:
local Events = require(Events)
-- on the server:
local EquipItem = Events.EquipItem:server()
-- or on the client:
local DropItem = Events.DropItem:client()
Executor Methods
Access a client-side executor by calling :client()
on the selected event or function. To access the server-sided executor, call :server()
on the selected event or function.
Events
fire(player: Player | { Player }, Args...): ()
Fires the event with the given arguments to the selected player or players
broadcast(Args...): ()
Fires the event with the given arguments to all players
except(player: Player | { Player }, Args...): ()
Fires the event with the given arguments to all players except the given ones
connect(callback: (player: Player, Args...) -> ()): RBXScriptConnection
Connects the callback to the event's OnServerEvent
Functions
invoke(player: Player, ...Args): ...Returns
Invokes the function on the specified players with the given arguments and returns the defined returns
connect(callback: (player: Player, ...Args) -> ...Returns): ()
Connects the callback to the event's OnServerInvoke
Last updated