# Table of Contents - [Introduction | RbxNet](#introduction-rbxnet) - [Install for TypeScript | RbxNet](#install-for-typescript-rbxnet) - [Introduction | RbxNet](#introduction-rbxnet) - [Getting started | RbxNet](#getting-started-rbxnet) - [Creating a definition | RbxNet](#creating-a-definition-rbxnet) - [Using your definitions | RbxNet](#using-your-definitions-rbxnet) - [Install for Luau | RbxNet](#install-for-luau-rbxnet) - [Using Compile Time Remote IDs | RbxNet](#using-compile-time-remote-ids-rbxnet) - [Runtime Type Checking | RbxNet](#runtime-type-checking-rbxnet) - [Rate limiting your remotes | RbxNet](#rate-limiting-your-remotes-rbxnet) - [Scoping with namespaces | RbxNet](#scoping-with-namespaces-rbxnet) - [Net.Server Namespace | RbxNet](#net-server-namespace-rbxnet) - [Wrapping Custom Player Objects | RbxNet](#wrapping-custom-player-objects-rbxnet) - [Net.Middleware Namespace | RbxNet](#net-middleware-namespace-rbxnet) - [Net.Client Namespace | RbxNet](#net-client-namespace-rbxnet) - [Net.Definitions Namespace | RbxNet](#net-definitions-namespace-rbxnet) - [Introduction | RbxNet](#introduction-rbxnet) - [Logging | RbxNet](#logging-rbxnet) - [Writing custom middleware | RbxNet](#writing-custom-middleware-rbxnet) - [API Overview | RbxNet](#api-overview-rbxnet) - [Install for TypeScript | RbxNet](#install-for-typescript-rbxnet) - [Install for TypeScript | RbxNet](#install-for-typescript-rbxnet) - [Install for Luau | RbxNet](#install-for-luau-rbxnet) - [Getting started | RbxNet](#getting-started-rbxnet) - [Using your definitions | RbxNet](#using-your-definitions-rbxnet) - [Creating a definition | RbxNet](#creating-a-definition-rbxnet) - [Using Compile Time Remote IDs | RbxNet](#using-compile-time-remote-ids-rbxnet) - [Runtime Type Checking | RbxNet](#runtime-type-checking-rbxnet) - [Wrapping Custom Player Objects | RbxNet](#wrapping-custom-player-objects-rbxnet) - [Rate limiting your remotes | RbxNet](#rate-limiting-your-remotes-rbxnet) - [API Overview | RbxNet](#api-overview-rbxnet) - [Net.Server Namespace | RbxNet](#net-server-namespace-rbxnet) - [Net.Client Namespace | RbxNet](#net-client-namespace-rbxnet) - [Using namespaces | RbxNet](#using-namespaces-rbxnet) - [Logging | RbxNet](#logging-rbxnet) - [Writing custom middleware | RbxNet](#writing-custom-middleware-rbxnet) - [Net.Definitions Namespace | RbxNet](#net-definitions-namespace-rbxnet) - [Net.Middleware Namespace | RbxNet](#net-middleware-namespace-rbxnet) - [Install for Luau | RbxNet](#install-for-luau-rbxnet) - [Runtime Type Checking | RbxNet](#runtime-type-checking-rbxnet) - [API Overview | RbxNet](#api-overview-rbxnet) - [Using Compile Time Remote IDs | RbxNet](#using-compile-time-remote-ids-rbxnet) - [Writing custom middleware | RbxNet](#writing-custom-middleware-rbxnet) - [Rate limiting your remotes | RbxNet](#rate-limiting-your-remotes-rbxnet) - [Basics | RbxNet](#basics-rbxnet) - [Net.Server Namespace | RbxNet](#net-server-namespace-rbxnet) - [Basics | RbxNet](#basics-rbxnet) - [Net.Middleware Namespace | RbxNet](#net-middleware-namespace-rbxnet) - [Wrapping Custom Player Objects | RbxNet](#wrapping-custom-player-objects-rbxnet) - [Net.Client Namespace | RbxNet](#net-client-namespace-rbxnet) - [Logging | RbxNet](#logging-rbxnet) - [Net.Definitions Namespace | RbxNet](#net-definitions-namespace-rbxnet) - [Basics | RbxNet](#basics-rbxnet) - [Leveraging the Definitions API | RbxNet](#leveraging-the-definitions-api-rbxnet) - [Page Not Found | RbxNet](#page-not-found-rbxnet) - [Page Not Found | RbxNet](#page-not-found-rbxnet) - [Page Not Found | RbxNet](#page-not-found-rbxnet) - [Page Not Found | RbxNet](#page-not-found-rbxnet) --- # Introduction | RbxNet Version: 3.0.10 ![Net Logo](https://rbxnet.australis.dev/img/net2.svg) Roblox Networking (RbxNet) v3.0 =============================== [](https://www.npmjs.com/package/@rbxts/net) RbxNet is a _networking library_ for Roblox, built in TypeScript. It simplifies the creation and management of networking in Roblox. Features[#](https://rbxnet.australis.dev/docs/3.0/#features "Direct link to heading") -------------------------------------------------------------------------------------- * Creation and usage of remotes through "identifiers". Management of the remotes themselves are done by Net itself. * More explicit, contextual APIs. `Net.Server` for server-based API, and `Net.Client` for client-based API. * Ability for remote definitions through `Net.Definitions`. Remotes done through this API are auto-generated. * Asynchronous functions - `Net.*.AsyncFunction`. No more pitfalls of regular remote functions. * Asynchronous callbacks and methods: because it's a roblox-ts library, it supports promises. * Middleware - Ability to add your own custom behaviours to remotes. Net comes with a runtime type checker, and a rate limiter middleware. * `Net.*.GameMessagingEvent` - interact with `MessagingService` like you would with regular remote events. Cross-server communication with the simple API. All the limitations are handled by Net. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/doc1.md) * [Features](https://rbxnet.australis.dev/docs/3.0/#features) --- # Install for TypeScript | RbxNet Version: 3.0.10 The TypeScript version of RbxNet requires knowledge and usage of [roblox-ts](https://roblox-ts.com/) . Install via Node Package Manager (NPM) _(Recommended)_[#](https://rbxnet.australis.dev/docs/3.0/install#install-via-node-package-manager-npm--recommended "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ RbxNet is available on NPM. To install it to your roblox-ts project, type the following in command line/terminal npm install @rbxts/net Copy Once you have the module installed, you can then use it in code by importing it as such: import Net from "@rbxts/net"; Copy Install from GitHub[#](https://rbxnet.australis.dev/docs/3.0/install#install-from-github "Direct link to heading") ------------------------------------------------------------------------------------------------------------------- This is the option to use if you're wanting to use the latest master build of rbx-net. It's recommended though you use the above NPM option. npm install github:roblox-aurora/rbx-net Copy Once you have the module installed, you can then use it in code by importing it as such: import Net from "@rbxts/net"; Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/install.md) * [Install via Node Package Manager (NPM) _(Recommended)_](https://rbxnet.australis.dev/docs/3.0/install#install-via-node-package-manager-npm--recommended) * [Install from GitHub](https://rbxnet.australis.dev/docs/3.0/install#install-from-github) --- # Introduction | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/) ** (3.0.10). Version: 2.1.5 ![Net Logo](https://rbxnet.australis.dev/img/net2.svg) Roblox Networking (RbxNet) v2.1 =============================== [](https://www.npmjs.com/package/@rbxts/net) RbxNet is a _networking library_ for Roblox, built in TypeScript. It simplifies the creation and management of networking in Roblox. Features[#](https://rbxnet.australis.dev/docs/2.1/#features "Direct link to heading") -------------------------------------------------------------------------------------- * Creation and usage of remotes through "identifiers". Management of the remotes themselves are done by Net itself. * More explicit, contextual APIs. `Net.Server` for server-based API, and `Net.Client` for client-based API. * Ability for remote definitions through `Net.Definitions`. * Asynchronous functions - `Net.*.AsyncFunction`. No more pitfalls of regular remote functions. * Asynchronous callbacks and methods: because it's a roblox-ts library, it supports promises. * Middleware - Ability to add your own custom behaviours to remotes. Net comes with a runtime type checker, and a rate limiter middleware. * `Net.*.GameMessagingEvent` - interact with `MessagingService` like you would with regular remote events. Cross-server communication with the simple API. All the limitations are handled by Net. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/doc1.md) * [Features](https://rbxnet.australis.dev/docs/2.1/#features) --- # Getting started | RbxNet Version: 3.0.10 What are definitions?[#](https://rbxnet.australis.dev/docs/3.0/definitions#what-are-definitions "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------- Definitions are a sort of "blueprint" for all the networking related objects in your game or library. It's a single source of truth in which all the code in your game can access remotes through, to handle your game or library's networking. Creating a definition script[#](https://rbxnet.australis.dev/docs/3.0/definitions#creating-a-definition-script "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------- To use definitions, you will need to create a script that is somewhere in `ReplicatedStorage` (or inside the library itself if you're doing it for a library). It needs to be accessible by both server scripts and client scripts. The basic declaration of a definition script, is the following: * roblox-ts * luau shared/remotes.ts import Net from "@rbxts/net"; const Remotes \= Net.CreateDefinitions({ // Definitions for the actual remotes will go here }); export \= Remotes; Copy src/shared/remotes.lua local Net \= require(ReplicatedStorage.Net) local Remotes \= Net.CreateDefinitions({ \-- Definitions for the actual remotes will go here }) return Remotes Copy Then simply, you can import the module from your code, and use the definitions API to get the remotes [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/definitions/00-overview.md) * [What are definitions?](https://rbxnet.australis.dev/docs/3.0/definitions#what-are-definitions) * [Creating a definition script](https://rbxnet.australis.dev/docs/3.0/definitions#creating-a-definition-script) --- # Creating a definition | RbxNet Version: 3.0.10 In RbxNet, there are three categories of remote objects: * **Event** - This is analogous to a `RemoteEvent`. This is what is used if you want to send an event (like an action) to the server or a player. * **AsyncFunction** - This is _like_ a `RemoteFunction`, but uses `RemoteEvent` internally. The difference with this and `Function` is that `AsyncFunction` _will_ handle time outs and runs completely asynchronously. (meaning it wont yield code) If there is no response from the reciever, it will reject. * **Function** - This is analogous to a `RemoteFunction`. However unlike a regular `RemoteFunction` this does not allow you to call a client. This is for security reasons discussed [here](https://github.com/roblox-aurora/rbx-net/issues/13) Defining Events & Functions[#](https://rbxnet.australis.dev/docs/3.0/definitions/starting#defining-events--functions "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------- Given the above knowledge, we can then apply that to our remote definition script. There are the following functions under `Net.Definitions` for creating definitions for the three categories we have above. The API for each type of definition is explicit so it is easy to understand what each defined remote does. ### The different types of definitions[#](https://rbxnet.australis.dev/docs/3.0/definitions/starting#the-different-types-of-definitions "Direct link to heading") * Event * **`Net.Definitions.ServerToClientEvent`** - Defines an event in which the server sends an event to one or many clients * **`Net.Definitions.ClientToServerEvent`** - Defines an event in which the client send events to the server * **`Net.Definitions.BidirectionalEvent`** - Defines an event in which both the server can send an event to one or many clients, and also the clients can send events to the server. _This should only be used in cases where it's required_. * AsyncFunction * **`Net.Definitions.ServerAsyncFunction`** - Defines an async function which exists on the server, and can be called by clients. The returned result will be recieved on the client as a promise. * **`Net.Definitions.ClientAsyncFunction`** - Defines an async function which exists on the client, and can be called by the server. The returned result will be recieved on the server as a promise. * Function * **`Net.Definitions.ServerFunction`** - Defines a synchronous function which exists on the server, and can be called by clients * Broadcast * **`Net.Definitions.ExperienceBroadcastEvent`** - Defines an event that the server can use to communicate with other servers in the same experience ### Defining remotes[#](https://rbxnet.australis.dev/docs/3.0/definitions/starting#defining-remotes "Direct link to heading") With the above knowledge, we can create a few example definitions. Say I would like a use case like the following ![](data:image/png;base64,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) * roblox-ts * luau shared/remotes.ts import Net, { Definitions } from "@rbxts/net"; const Remotes \= Net.CreateDefinitions({ GetPlayerInventory: Definitions.ServerAsyncFunction<() \=> SerializedPlayerInventory\>(), GetPlayerEquipped: Definitions.ServerAsyncFunction<() \=> SerializedPlayerEquipped\>(), PlayerInventoryUpdated: Definitions.ServerToClientEvent<\[event: InventoryUpdatedEvent\]\>(), PlayerEquippedUpdated: Definitions.ServerToClientEvent<\[event: EquippedUpdatedEvent\]\>(), PlayerUnequipItem: Definitions.ClientToServerEvent<\[itemId: number\]\>(), PlayerEquipItem: Definitions.ClientToServerEvent<\[itemId: number\]\>(), }); export \= Remotes; Copy src/shared/remotes.lua local Net \= require(ReplicatedStorage.Net) local Remotes \= Net.CreateDefinitions({ GetPlayerInventory \= Net.Definitions.ServerFunction(), GetPlayerEquipped \= Net.Definitions.ServerFunction(), PlayerInventoryUpdated \= Net.Definitions.ServerToClientEvent(), PlayerEquippedUpdated \= Net.Definitions.ServerToClientEvent(), PlayerUnequipItem \= Net.Definitions.ClientToServerEvent(), PlayerEquipItem \= Net.Definitions.ClientToServerEvent(), }) return Remotes Copy Straight away you can see it's quite easy to know what remote does what. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/definitions/01-starting.md) * [Defining Events & Functions](https://rbxnet.australis.dev/docs/3.0/definitions/starting#defining-events--functions) * [The different types of definitions](https://rbxnet.australis.dev/docs/3.0/definitions/starting#the-different-types-of-definitions) * [Defining remotes](https://rbxnet.australis.dev/docs/3.0/definitions/starting#defining-remotes) --- # Using your definitions | RbxNet Version: 3.0.10 Say that we have our example definition file here: * roblox-ts * luau shared/remotes.ts import Net, { Definitions } from "@rbxts/net"; const Remotes \= Net.CreateDefinitions({ GetPlayerInventory: Definitions.ServerAsyncFunction<() \=> SerializedPlayerInventory\>(), GetPlayerEquipped: Definitions.ServerAsyncFunction<() \=> SerializedPlayerEquipped\>(), PlayerInventoryUpdated: Definitions.ServerToClientEvent<\[event: InventoryUpdatedEvent\]\>(), PlayerEquippedUpdated: Definitions.ServerToClientEvent<\[event: EquippedUpdatedEvent\]\>(), PlayerUnequipItem: Definitions.ClientToServerEvent<\[itemId: number\]\>(), PlayerEquipItem: Definitions.ClientToServerEvent<\[itemId: number\]\>(), }); export \= Remotes; Copy src/shared/remotes.lua local Net \= require(ReplicatedStorage.Net) local Remotes \= Net.CreateDefinitions({ GetPlayerInventory \= Net.Definitions.ServerFunction(), GetPlayerEquipped \= Net.Definitions.ServerFunction(), PlayerInventoryUpdated \= Net.Definitions.ServerToClientEvent(), PlayerEquippedUpdated \= Net.Definitions.ServerToClientEvent(), PlayerUnequipItem \= Net.Definitions.ClientToServerEvent(), PlayerEquipItem \= Net.Definitions.ClientToServerEvent(), }) return Remotes Copy How would we approach using this to actually be able to send messages between the server and client? Usage[#](https://rbxnet.australis.dev/docs/3.0/definitions/using#usage "Direct link to heading") ------------------------------------------------------------------------------------------------- * roblox-ts * luau server/main.server.ts import Remotes from "shared/remotes"; Copy src/server/main.server.lua local Remotes \= require(ReplicatedStorage.Shared.Remotes) Remotes.Server:Get("PlayerEquipItem"):Connect(function(player: Player, text: string) print("Received "..text.." from "..player.Name) end) Copy src/client/test.client.lua local Remotes \= require(ReplicatedStorage.Shared.Remotes) Remotes.Client:Get("PlayerEquipItem"):SendToServer("Hey!") Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/definitions/02-implementation.md) * [Usage](https://rbxnet.australis.dev/docs/3.0/definitions/using#usage) --- # Install for Luau | RbxNet Version: 3.0.10 Depending on your stack for Roblox, you might want to either use the [Rojo](https://rbxnet.australis.dev/docs/3.0/install-luau#via-rojo) step or the [Studio](https://rbxnet.australis.dev/docs/3.0/install-luau#via-studio) step. If you don't know what _Rojo_ is, use the Studio step. Via Rojo[#](https://rbxnet.australis.dev/docs/3.0/install-luau#via-rojo "Direct link to heading") -------------------------------------------------------------------------------------------------- The following steps require knowledge and use of [rojo](https://rojo.space/) . If you're not using rojo, look at [studio](https://rbxnet.australis.dev/docs/3.0/install-luau#via-studio) instructions. ### Install via Wally _(Recommended)_[#](https://rbxnet.australis.dev/docs/3.0/install-luau#install-via-wally-recommended "Direct link to heading") First, if you haven't already - [Install Wally](https://github.com/UpliftGames/wally) . Then, in your `wally.toml` file for your project, put under `dependencies`: \# ... \[dependencies\] \# ... Net \= "vorlias/net@3.0.1" Copy Then run wally install Copy Via Studio[#](https://rbxnet.australis.dev/docs/3.0/install-luau#via-studio "Direct link to heading") ------------------------------------------------------------------------------------------------------ ### RBXMX model file[#](https://rbxnet.australis.dev/docs/3.0/install-luau#rbxmx-model-file "Direct link to heading") Releases can be found [here](https://github.com/roblox-aurora/rbx-net/releases) . Download the appropriate `.rbxmx` file under the `Assets` dropdown, then drag it into studio. Ensure the library is under `ReplicatedStorage` so it can be used by all your code. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/install-lua.md) * [Via Rojo](https://rbxnet.australis.dev/docs/3.0/install-luau#via-rojo) * [Install via Wally _(Recommended)_](https://rbxnet.australis.dev/docs/3.0/install-luau#install-via-wally-recommended) * [Via Studio](https://rbxnet.australis.dev/docs/3.0/install-luau#via-studio) * [RBXMX model file](https://rbxnet.australis.dev/docs/3.0/install-luau#rbxmx-model-file) --- # Using Compile Time Remote IDs | RbxNet Version: 3.0.10 ##### TypeScript Only This functionality is only available to roblox-ts users. This is not possible in regular Luau. This method uses a transformer called [`rbxts-transform-guid`](https://github.com/roblox-aurora/rbxts-transform-guid) and is quite experimental. Installation[#](https://rbxnet.australis.dev/docs/3.0/uuid#installation "Direct link to heading") -------------------------------------------------------------------------------------------------- npm i -D rbxts-transform-guid Copy Once installed, you will need to configure it in your tsconfig.json under `plugins`: { "compilerOptions": { // .. "plugins": \[\ \ // ...\ \ {\ \ "transform": "rbxts-transform-guid",\ \ "EXPERIMENTAL\_JSDocConstEnumUUID": true\ \ }\ \ \] } } Copy Then if you want to create remote ids, you create a `const enum` like such: /\*\* \* @uuid \*/ export const enum RemoteId { GetPlayerInventory \= "GetPlayerInventory" } Copy `uuid` is important here, it's what tells our transformer to convert our enum values to guids at compile time. Then in your definition file you can use it as such: src/shared/remotes.ts import Net from "@rbxts/net"; /\*\* \* @uuid \*/ export const enum RemoteId { GetPlayerInventory \= "GetPlayerInventory" } const Remotes \= Net.CreateDefinitions({ \[RemoteId.GetPlayerInventory\]: Net.Definitions.ServerAsyncFunction<() \=> InventorySlot\[\]\>(), }); export default Remotes; Copy Then you can use it as such: src/server/example.server.ts import Remotes, { RemoteId } from "src/shared/remotes"; const getPlayerInventory \= Remotes.Server.Get(RemoteId.GetPlayerInventory); // ... Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/guides/uuid.md) * [Installation](https://rbxnet.australis.dev/docs/3.0/uuid#installation) --- # Runtime Type Checking | RbxNet Version: 3.0.10 It's important when you recieve events or calls from the server that you ensure the types are correct, otherwise unwanted errors may pop up. If you want to ensure the types you're recieving from the client _are_ the types you're expecting, you can use the [`Net.Middleware.TypeChecking`](https://rbxnet.australis.dev/docs/3.0/middleware/api/middleware#typechecking) middleware. This middleware just takes type checking functions. Using a library like [`t`](https://github.com/osyrisrblx/t) [#](https://rbxnet.australis.dev/docs/3.0/middleware/types#using-a-library-like-t "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The type checking middleware is created as such: * roblox-ts * luau Net.Middleware.TypeCheck(t.string) Copy local t \= require(ReplicatedStorage.Libs.t) local Remotes \= Net.CreateDefinitions({ Click \= Net.Definitions.ClientToServerEvent({ Net.Middleware.TypeChecking(t.Vector3, t.string) }) }) Copy or local function typeCheckString(check: any) return typeof(check) \== "string" end local function typeCheckVector3(check: any) return typeof(check) \== "Vector3" end local Remotes \= Net.CreateDefinitions({ Click \= Net.Definitions.ClientToServerEvent({ Net.Middleware.TypeChecking(typeCheckVector3, typeCheckString) }) }) Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/middleware/typecheck.md) * [Using a library like t](https://rbxnet.australis.dev/docs/3.0/middleware/types#using-a-library-like-t) --- # Rate limiting your remotes | RbxNet Version: 3.0.10 Your event or AsyncFunction may perform an intensive task that you don't want players to be able to invoke every second (and possibly crash your game) A way you can get around this is by using the [`Net.Middleware.RateLimit`](https://rbxnet.australis.dev/docs/3.0/middleware/api/middleware#ratelimit) middleware. This is a built in. Limiting to a certain amount of requests[#](https://rbxnet.australis.dev/docs/3.0/middleware/rate-limit#limiting-to-a-certain-amount-of-requests "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The rate limiter middleware is created as such: * roblox-ts * luau Net.Middleware.RateLimit({ MaxRequestsPerMinute: 1 // This can be the amount of requests you want to limit per minute }) Copy Net.Middleware.RateLimit({ MaxRequestsPerMinute \= 1 \-- This can be the amount of requests you want to limit per minute }) Copy Then you pass it to a constructor for a server object, or a definition: * roblox-ts * luau const Remotes \= Net.Definitions.Create({ Example: Net.Definitions.AsyncFunction(\[\ \ Net.Middleware.RateLimit({\ \ MaxRequestsPerMinute: 1\ \ })\ \ \]) }) Copy local Remotes \= Net.Definitions.Create({ Example \= Net.Definitions.AsyncFunction({ Net.Middleware.RateLimit({ MaxRequestsPerMinute \= 1 }) }) }) Copy Custom Error Handling[#](https://rbxnet.australis.dev/docs/3.0/middleware/rate-limit#custom-error-handling "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------- When the rate limit is reached, it will run the error handler. By default this is set to a function which displays a warning on the server: export function rateLimitWarningHandler(error: RateLimitError) { warn("\[rbx-net\]", error.Message); } Copy However, if you want to send this to something like analytics, you can provide your own error handler: * roblox-ts * luau function analyticRateLimitError(error: RateLimitError) { AnalyticsService.Error(error.Message); // this is just an example } Copy const Remotes \= Net.Definitions.Create({ Example: Net.Definitions.AsyncFunction(\[\ \ Net.Middleware.RateLimit({\ \ MaxRequestsPerMinute: 1,\ \ ErrorHandler: analyticRateLimitError\ \ })\ \ \]) }) Copy local function analyticRateLimitError(error) AnalyticsService:Error(error.Message) \-- this is just an example end Copy local Remotes \= Net.Definitions.Create({ Example \= Net.Definitions.AsyncFunction({ Net.Middleware.RateLimit({ MaxRequestsPerMinute \= 1, ErrorHandler \= analyticRateLimitError }) }) }) Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/middleware/ratelimit.md) * [Limiting to a certain amount of requests](https://rbxnet.australis.dev/docs/3.0/middleware/rate-limit#limiting-to-a-certain-amount-of-requests) * [Custom Error Handling](https://rbxnet.australis.dev/docs/3.0/middleware/rate-limit#custom-error-handling) --- # Scoping with namespaces | RbxNet Version: 3.0.10 As your game grows, so too will your definitions file. To better organize your networking definitions, RbxNet introduces a concept called "Namespaces". Namespaces are like sub-definitions. They can also be stored in separate files to be included in the main definition file. Creating a namespace[#](https://rbxnet.australis.dev/docs/3.0/definitions/namespacing#creating-a-namespace "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------- Going by our previous example, say we want to separate up inventory and equipment remotes into separate files: * roblox-ts * luau shared/remotes.ts import Net, { Definitions } from "@rbxts/net"; const Remotes \= Net.CreateDefinitions({ // These are all remotes relating to the inventory Inventory: Definitions.Namespace({ GetPlayerInventory: Definitions.ServerAsyncFunction<() \=> SerializedPlayerInventory\>(), PlayerInventoryUpdated: Definitions.ServerToClientEvent<\[event: InventoryUpdatedEvent\]\>(), }), // These are all the remotes relating to equipping Equipping: Definitions.Namespace({ GetPlayerEquipped: Definitions.ServerAsyncFunction<() \=> SerializedPlayerEquipped\>(), PlayerEquippedUpdated: Definitions.ServerToClientEvent<\[event: EquippedUpdatedEvent\]\>(), PlayerUnequipItem: Definitions.ClientToServerEvent<\[itemId: number\]\>(), PlayerEquipItem: Definitions.ClientToServerEvent<\[itemId: number\]\>(), }) }); export \= Remotes; Copy src/shared/remotes.lua local Net \= require(ReplicatedStorage.Net) local Remotes \= Net.CreateDefinitions({ \-- These are all remotes relating to the inventory Inventory \= Net.Definitions.Namespace({ PlayerInventoryUpdated \= Net.Definitions.ServerToClientEvent(), GetPlayerInventory \= Net.Definitions.ServerFunction(), }), \-- These are all the remotes relating to equipping Equipped \= Net.Definitions.Namespace({ GetPlayerEquipped \= Net.Definitions.ServerFunction(), PlayerEquippedUpdated \= Net.Definitions.ServerToClientEvent(), PlayerUnequipItem \= Net.Definitions.ClientToServerEvent(), PlayerEquipItem \= Net.Definitions.ClientToServerEvent(), }), }) return Remotes Copy Then simply, if you want to do the same fetch: Usage from the server[#](https://rbxnet.australis.dev/docs/3.0/definitions/namespacing#usage-from-the-server "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------------- * roblox-ts * luau server/main.server.ts import Remotes from "shared/remotes"; // This will contain all the server inventory remotes const InventoryRemotes \= Remotes.Server.GetNamespace("Inventory"); // This will contain all the server equipped remotes const equippedRemotes \= Remotes.Server.GetNamespace("Equipped"); Copy src/server/main.server.lua local Remotes \= require(ReplicatedStorage.Shared.Remotes) \-- This will contain all the server inventory remotes local EquippedRemotes \= Remotes.Server:GetNamespace("Equipped") \-- This will contain all the client inventory remotes local InventoryRemotes \= Remotes.Server:GetNamespace("Inventory") Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/definitions/03-namespacing.md) * [Creating a namespace](https://rbxnet.australis.dev/docs/3.0/definitions/namespacing#creating-a-namespace) * [Usage from the server](https://rbxnet.australis.dev/docs/3.0/definitions/namespacing#usage-from-the-server) --- # Net.Server Namespace | RbxNet Version: 3.0.10 This contains all the server-related code relating to Net Event[#](https://rbxnet.australis.dev/docs/3.0/api/server#event "Direct link to heading") ------------------------------------------------------------------------------------------ class ServerEvent { constructor(name: string, middleware?: Middleware); GetInstance(): RemoteEvent; Connect(callback: (player: Player, ...args: ConnectArgs) \=> void): RBXScriptConnection; SendToAllPlayers(...args: CallArgs): void; SendToAllPlayersExcept(blacklist: Player | Player\[\], ...args: CallArgs): void; SendToPlayer(player: Player, ...args: CallArgs): void; SendToPlayers(players: Player\[\], ...args: CallArgs): void; } Copy ### GetInstance[#](https://rbxnet.australis.dev/docs/3.0/api/server#getinstance "Direct link to heading") ### Connect[#](https://rbxnet.australis.dev/docs/3.0/api/server#connect "Direct link to heading") ### SendToAllPlayers[#](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoallplayers "Direct link to heading") ### SendToAllPlayersExcept[#](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoallplayersexcept "Direct link to heading") ### SendToPlayer[#](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoplayer "Direct link to heading") ### SendToPlayers[#](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoplayers "Direct link to heading") Function[#](https://rbxnet.australis.dev/docs/3.0/api/server#function "Direct link to heading") ------------------------------------------------------------------------------------------------ class ServerFunction { constructor(name: string, middleware?: Middleware); GetInstance(): RemoteFunction; SetCallback(callback: (player: Player, ...args: CallbackArgs) \=> Returns): void; } Copy ### GetInstance[#](https://rbxnet.australis.dev/docs/3.0/api/server#getinstance-1 "Direct link to heading") ### SetCallback[#](https://rbxnet.australis.dev/docs/3.0/api/server#setcallback "Direct link to heading") AsyncFunction[#](https://rbxnet.australis.dev/docs/3.0/api/server#asyncfunction "Direct link to heading") ---------------------------------------------------------------------------------------------------------- class ServerAsyncFunction { constructor(name: string, middleware?: Middleware); GetInstance(): RemoteEvent; SetCallback(callback: (player: Player, ...args: CallbackArgs) \=> any): void; CallPlayerAsync(player: Player, ...args: CallArgs): Promise; } Copy ### GetInstance[#](https://rbxnet.australis.dev/docs/3.0/api/server#getinstance-2 "Direct link to heading") ### SetCallback[#](https://rbxnet.australis.dev/docs/3.0/api/server#setcallback-1 "Direct link to heading") ### CallPlayerAsync[#](https://rbxnet.australis.dev/docs/3.0/api/server#callplayerasync "Direct link to heading") CrossServerEvent[#](https://rbxnet.australis.dev/docs/3.0/api/server#crossserverevent "Direct link to heading") ---------------------------------------------------------------------------------------------------------------- class CrossServerEvent { constructor(name: string); SendToAllServers(...args: unknown\[\]): void; SendToServer(jobId: string, ...args: unknown\[\]): void; SendToPlayer(userId: number, ...args: unknown\[\]): void; SendToPlayers(userIds: number\[\], ...args: unknown\[\]): void; Disconnect(): void; } Copy ### SendToAllServers[#](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoallservers "Direct link to heading") ### SendToServer[#](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoserver "Direct link to heading") ### SendToPlayer[#](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoplayer-1 "Direct link to heading") ### SendToPlayers[#](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoplayers-1 "Direct link to heading") ### Disconnect[#](https://rbxnet.australis.dev/docs/3.0/api/server#disconnect "Direct link to heading") [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/api/net-server.md) * [Event](https://rbxnet.australis.dev/docs/3.0/api/server#event) * [GetInstance](https://rbxnet.australis.dev/docs/3.0/api/server#getinstance) * [Connect](https://rbxnet.australis.dev/docs/3.0/api/server#connect) * [SendToAllPlayers](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoallplayers) * [SendToAllPlayersExcept](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoallplayersexcept) * [SendToPlayer](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoplayer) * [SendToPlayers](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoplayers) * [Function](https://rbxnet.australis.dev/docs/3.0/api/server#function) * [GetInstance](https://rbxnet.australis.dev/docs/3.0/api/server#getinstance-1) * [SetCallback](https://rbxnet.australis.dev/docs/3.0/api/server#setcallback) * [AsyncFunction](https://rbxnet.australis.dev/docs/3.0/api/server#asyncfunction) * [GetInstance](https://rbxnet.australis.dev/docs/3.0/api/server#getinstance-2) * [SetCallback](https://rbxnet.australis.dev/docs/3.0/api/server#setcallback-1) * [CallPlayerAsync](https://rbxnet.australis.dev/docs/3.0/api/server#callplayerasync) * [CrossServerEvent](https://rbxnet.australis.dev/docs/3.0/api/server#crossserverevent) * [SendToAllServers](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoallservers) * [SendToServer](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoserver) * [SendToPlayer](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoplayer-1) * [SendToPlayers](https://rbxnet.australis.dev/docs/3.0/api/server#sendtoplayers-1) * [Disconnect](https://rbxnet.australis.dev/docs/3.0/api/server#disconnect) --- # Wrapping Custom Player Objects | RbxNet Version: 3.0.10 How one might do it[#](https://rbxnet.australis.dev/docs/3.0/custom-player-objects#how-one-might-do-it "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------- A common pattern when using remotes - on the server - is to require casting a player to an object representation of the player. This may come as the following sort of situation: * roblox-ts * luau import Remotes from "shared/remotes"; import PlayerService from "server/Services/PlayerService"; const PlayerEquipItem \= Remotes.Server.Get("PlayerEquipItem"); PlayerEquipItem.Connect((player, itemId) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { entity.EquipItem(itemId); } }) const PlayerUnequipItem \= Remotes.Server.Get("PlayerUnequipItem") PlayerUnequipItem.Connect((player, itemId) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { entity.UnequipItem(itemId); } }) const GetPlayerEquipped \= Remotes.Server.Get("GetPlayerEquipped") GetPlayerEquipped.SetCallback((player) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { return entity.GetEquippedItems(); } }) Copy local PlayerService \= require(ServerScriptService.Services.PlayerService) local Remotes \= require(ReplicatedStorage.Remotes) local PlayerEquipItem \= Remotes.Server:Get("PlayerEquipItem") PlayerEquipItem:Connect(function (player, itemId) local entity \= PlayerService:GetEntity(player) if entity then entity:EquipItem(itemId) end end) local PlayerUnequipItem \= Remotes.Server:Get("PlayerUnequipItem") PlayerUnequipItem:Connect(function (player, itemId) local entity \= PlayerService:GetEntity(player) if entity then entity:UnequipItem(itemId) end end) local GetPlayerEquipped \= Remotes.Server:Get("GetPlayerEquipped") GetPlayerEquipped:SetCallback(function(player) local entity \= PlayerService:GetEntity(player) if entity then return entity:GetEquippedItems() end end) Copy As you might have noticed, there's some repeated code where we're repetitively having to grab the player entity here in place of the player. We can instead use what's called a _wrapper_ to do this for us and make it as if we were connecting directly to the remote and it had the entity as the player argument rather than a player. Using a wrapper[#](https://rbxnet.australis.dev/docs/3.0/custom-player-objects#using-a-wrapper "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------- We can define a `withPlayerEntity` wrapper, which will achieve what we're doing above in each remote separately. This is the recommended method when augmenting the player argument as it's the safest method and guaranteed to run after all the middleware. * roblox-ts * luau server/Wrappers/withPlayerEntity.ts import PlayerService from "server/Services/PlayerService"; import PlayerEntity from "server/Classes/PlayerEntity"; export default function withPlayerEntity, R \= void\>( fn: (playerEntity: PlayerEntity, ...args: T) \=> R, ) { return (player: Player, ...args: T) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { return fn(entity, ...args); } }; } Copy src/server/Wrappers/withPlayerEntity.lua local PlayerService \= require(ServerScriptService.Services.PlayerService) local function withPlayerEntity(fn) return function (player, ...) local entity \= playerService:GetEntity(player) if entity then return fn(entity, ...) end end end return withPlayerEntity Copy Then we can apply this to the code above. * roblox-ts * luau import PlayerService from "server/Services/PlayerService"; import Remotes from "shared/remotes"; import withPlayerEntity from "server/Wrappers/withPlayerEntity"; const PlayerEquipItem \= Remotes.Server.Get("PlayerEquipItem") PlayerEquipItem.Connect( withPlayerEntity((entity, itemId) \=> { entity.EquipItem(itemId); }) ); const PlayerUnequipItem \= Remotes.Server.Get("PlayerUnequipItem") PlayerUnequipItem.Connect((player, itemId) \=> { withPlayerEntity((entity, itemId) \=> { entity.UnequipItem(itemId); }) }) const GetPlayerEquipped \= Remotes.Server.Get("GetPlayerEquipped") GetPlayerEquipped.SetCallback( withPlayerEntity((player) \=> { return entity.GetEquippedItems(); }) ) Copy local PlayerService \= require(ServerScriptService.Services.PlayerService) local Remotes \= require(ReplicatedStorage.Remotes) local withPlayerEntity \= require(ServerScriptService.Wrappers.withPlayerEntity) local PlayerEquipItem \= Remotes.Server:Get("PlayerEquipItem") PlayerEquipItem:Connect( withPlayerEntity(function (entity, itemId) entity:EquipItem(itemId) end) ) local PlayerUnequipItem \= Remotes.Server:Get("PlayerUnequipItem") PlayerUnequipItem:Connect( withPlayerEntity(function (player, itemId) entity:UnequipItem(itemId) end) ) local GetPlayerEquipped \= Remotes.Server:Get("GetPlayerEquipped") GetPlayerEquipped:SetCallback( withPlayerEntity(function(player) return entity:GetEquippedItems() end) ) Copy And as you can see, this reduces repetitive code and gives us the `PlayerEntity` object to work with. Simple as that. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/guides/connect-wrapper.md) * [How one might do it](https://rbxnet.australis.dev/docs/3.0/custom-player-objects#how-one-might-do-it) * [Using a wrapper](https://rbxnet.australis.dev/docs/3.0/custom-player-objects#using-a-wrapper) --- # Net.Middleware Namespace | RbxNet Version: 3.0.10 TypeChecking[#](https://rbxnet.australis.dev/docs/3.0/api/middleware#typechecking "Direct link to heading") ------------------------------------------------------------------------------------------------------------ ### Basic Type Checker[#](https://rbxnet.australis.dev/docs/3.0/api/middleware#basic-type-checker "Direct link to heading") function TypeChecking(...checks: TypeCheck\[\]): TypeCheckingMiddleware Copy Function * Parameters * `...checks` Type checking functions in order of the arguments passed to the remote RateLimit[#](https://rbxnet.australis.dev/docs/3.0/api/middleware#ratelimit "Direct link to heading") ------------------------------------------------------------------------------------------------------ The built-in rate limiting middleware. interface RateLimitError { Message: string; UserId: number; RemoteId: string; MaxRequestsPerMinute: number; } interface RateLimitOptions { MaxRequestsPerMinute: number; ErrorHandler?: (error: RateLimitError) \=> void; } function RateLimit(options: RateLimitOptions): RateLimitingMiddleware Copy Function * Parameters * `options` The options for the rate limiter Logging[#](https://rbxnet.australis.dev/docs/3.0/api/middleware#logging "Direct link to heading") -------------------------------------------------------------------------------------------------- The built-in logging middleware interface LoggingOptions { Name?: string; Logger?: (name: string, args: unknown\[\]) \=> void; } function Logging(options?: LoggingOptions): LoggerMiddleware Copy Function * Parameters * `options` The options for the logger [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/api/net-middleware.md) * [TypeChecking](https://rbxnet.australis.dev/docs/3.0/api/middleware#typechecking) * [Basic Type Checker](https://rbxnet.australis.dev/docs/3.0/api/middleware#basic-type-checker) * [RateLimit](https://rbxnet.australis.dev/docs/3.0/api/middleware#ratelimit) * [Logging](https://rbxnet.australis.dev/docs/3.0/api/middleware#logging) --- # Net.Client Namespace | RbxNet Version: 3.0.10 This contains all the client-related code relating to Net Event[#](https://rbxnet.australis.dev/docs/3.0/api/client#event "Direct link to heading") ------------------------------------------------------------------------------------------ class ClientEvent { constructor(name: string); SendToServer(...args: CallArguments): void; Connect(callback: (...args: ConnectArgs) \=> void): RBXScriptConnection; } Copy ### SendToServer[#](https://rbxnet.australis.dev/docs/3.0/api/client#sendtoserver "Direct link to heading") ### Connect[#](https://rbxnet.australis.dev/docs/3.0/api/client#connect "Direct link to heading") Function[#](https://rbxnet.australis.dev/docs/3.0/api/client#function "Direct link to heading") ------------------------------------------------------------------------------------------------ class ClientFunction { constructor(name: string); CallServerAsync(...args: CallArgs): Promise; } Copy ### CallServerAsync[#](https://rbxnet.australis.dev/docs/3.0/api/client#callserverasync "Direct link to heading") AsyncFunction[#](https://rbxnet.australis.dev/docs/3.0/api/client#asyncfunction "Direct link to heading") ---------------------------------------------------------------------------------------------------------- class ClientAsyncFunction { constructor(name: string); CallServerAsync(...args: CallArgs): Promise; SetCallback(callback: (...args: CallbackArgs) \=> any): void; SetCallTimeout(timeout: number): void; GetCallTimeout(): number; } Copy ### CallServerAsync[#](https://rbxnet.australis.dev/docs/3.0/api/client#callserverasync-1 "Direct link to heading") ### SetCallback[#](https://rbxnet.australis.dev/docs/3.0/api/client#setcallback "Direct link to heading") ### SetCallTimeout[#](https://rbxnet.australis.dev/docs/3.0/api/client#setcalltimeout "Direct link to heading") ### GetCalllTimeout[#](https://rbxnet.australis.dev/docs/3.0/api/client#getcallltimeout "Direct link to heading") CrossServerEvent[#](https://rbxnet.australis.dev/docs/3.0/api/client#crossserverevent "Direct link to heading") ---------------------------------------------------------------------------------------------------------------- class CrossServerEvent { constructor(name: string); Connect(callback: (...args: unknown\[\]) \=> void): void; } Copy ### Connect[#](https://rbxnet.australis.dev/docs/3.0/api/client#connect-1 "Direct link to heading") [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/api/net-client.md) * [Event](https://rbxnet.australis.dev/docs/3.0/api/client#event) * [SendToServer](https://rbxnet.australis.dev/docs/3.0/api/client#sendtoserver) * [Connect](https://rbxnet.australis.dev/docs/3.0/api/client#connect) * [Function](https://rbxnet.australis.dev/docs/3.0/api/client#function) * [CallServerAsync](https://rbxnet.australis.dev/docs/3.0/api/client#callserverasync) * [AsyncFunction](https://rbxnet.australis.dev/docs/3.0/api/client#asyncfunction) * [CallServerAsync](https://rbxnet.australis.dev/docs/3.0/api/client#callserverasync-1) * [SetCallback](https://rbxnet.australis.dev/docs/3.0/api/client#setcallback) * [SetCallTimeout](https://rbxnet.australis.dev/docs/3.0/api/client#setcalltimeout) * [GetCalllTimeout](https://rbxnet.australis.dev/docs/3.0/api/client#getcallltimeout) * [CrossServerEvent](https://rbxnet.australis.dev/docs/3.0/api/client#crossserverevent) * [Connect](https://rbxnet.australis.dev/docs/3.0/api/client#connect-1) --- # Net.Definitions Namespace | RbxNet Version: 3.0.10 This namespace is for the Definitions feature. ### Definitions.Create(definitions)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionscreatedefinitions "Direct link to heading") function Create( remotes: T, globalMiddleware?: Net.GlobalMiddleware ): DefinitionBuilders Copy Function * Parameters * `remotes` An object of remote definitions. See [definitions](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitions-oh-my) for usage. * `globalMiddleware` (optional) A collection of _global middleware_ to apply to all remotes in this definition * Returns a [DefinitionsCreateResult](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionscreateresultt) Example shared/remotes.ts import Net from "@rbxts/net"; const MyDefinitions \= Net.Definitions.Create({ TestRemote: Net.Definitions.AsyncFunction<(name: string) \=> boolean\>() }); Copy ### Definitions.ServerFunction(...)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsserverfunctionserver "Direct link to heading") Definition function for creating a `FunctionDefinition` ### Definitions.ServerToClientEvent(...)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsservertoclienteventserverargs "Direct link to heading") Definition function for creating an `ServerEventDeclaration` ### Definitions.ClientToServerEvent(...)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsclienttoservereventclientargs "Direct link to heading") Definition function for creating an `ClientEventDeclaration` ### Definitions.BidirectionalEvent(...)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsbidirectionaleventserverargs-clientargs "Direct link to heading") Definition function for creating an `BidirectionalEventDeclaration` ### Definitions.ServerAsyncFunction(...)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsserverasyncfunctionserver "Direct link to heading") Definition function for creating an `ServerAsyncFunctionDefinition` ### Definitions.Namespace(definitions)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsnamespacedefinitions "Direct link to heading") Creates a group of definitions (returns `DeclarationNamespace`) DefinitionsCreateResult[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionscreateresultt "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------------- Contains the definition builders for a given definition (returned using [`Create`](https://rbxnet.australis.dev/docs/3.0/api/definitions/definitions#definitionscreatedefinitions) in Net.Definitions) interface DefinitionsCreateResult { readonly Server: ServerDefinitionBuilder; readonly Client: ClientDefinitionBuilder; } Copy ### Server[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#server "Direct link to heading") A [ServerDefinitionBuilder](https://rbxnet.australis.dev/docs/3.0/api/definitions/definitions#serverdefinitionbuildert) object. ### Client[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#client "Direct link to heading") A [ClientDefinitionBuilder](https://rbxnet.australis.dev/docs/3.0/api/definitions/definitions#clientdefinitionbuildert) object. ServerDefinitionBuilder[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#serverdefinitionbuildert "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------------- Contains all the definition builders for server-side events and functions. class ServerDefinitionBuilder { Get(name: string): ServerEvent | ServerAsyncFunction | ServerFunction; GetNamespace(name: K): SeverDefinitionBuilder; OnEvent(name: string, callback: Callback): void; OnFunction(name: string, callback: Callback): void; } Copy ### Get(name)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#getname "Direct link to heading") Will get the specified event by name, and return it. The returned object will be the type provided in the definition. server/example.server.ts import { Server as ServerRemotes } from "shared/remotes.ts"; const TestRemote \= ServerRemotes.Get("TestRemote"); Copy ### OnFunction(name, callback)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#onfunctionname-callback "Direct link to heading") Similar to `Get` but only works on events, and is pretty much a shortcut for `Get(name).SetCallback(callback)` ### OnEvent(name, callback)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#oneventname-callback "Direct link to heading") Similar to `Get` but only works on events, and is pretty much a shortcut for `Get(name).Connect(callback)` ### GetNamespace(name)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#getnamespacename "Direct link to heading") Gets a child namespace under this namespace ClientDefinitionBuilder[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#clientdefinitionbuildert "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------------- Contains all the definition builders for server-side events and functions. class ClientDefinitionBuilder { Get(name: string): ServerEvent | ServerAsyncFunction | ServerFunction; GetNamespace(name: K): ClientDefinitionBuilder; OnEvent(name: string, callback: Callback): void; OnFunction(name: string, callback: Callback): void; } Copy ### Get(name)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#getname-1 "Direct link to heading") Will get the specified event by name, and return it. The returned object will be the type provided in the definition. Gets the specified remote definition and gets the client version of the event/function/asyncfunction client/example.client.ts import { Client as ClientRemotes } from "shared/remotes.ts"; const TestRemote \= ClientRemotes.Get("TestRemote"); Copy ### OnEvent(name, callback)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#oneventname-callback-1 "Direct link to heading") Similar to `Get` but only works on events, and is pretty much a shortcut for `Get(name).Connect(callback)` ### OnFunction(name, callback)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#onfunctionname-callback-1 "Direct link to heading") Similar to `Get` but only works on events, and is pretty much a shortcut for `Get(name).SetCallback(callback)` ### GetNamespace(name)[#](https://rbxnet.australis.dev/docs/3.0/api/definitions#getnamespacename-1 "Direct link to heading") Gets a child namespace under this namespace [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/api/net-definitions.md) * [Definitions.Create(definitions)](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionscreatedefinitions) * [Definitions.ServerFunction(...)](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsserverfunctionserver) * [Definitions.ServerToClientEvent(...)](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsservertoclienteventserverargs) * [Definitions.ClientToServerEvent(...)](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsclienttoservereventclientargs) * [Definitions.BidirectionalEvent(...)](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsbidirectionaleventserverargs-clientargs) * [Definitions.ServerAsyncFunction(...)](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsserverasyncfunctionserver) * [Definitions.Namespace(definitions)](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionsnamespacedefinitions) * [DefinitionsCreateResult](https://rbxnet.australis.dev/docs/3.0/api/definitions#definitionscreateresultt) * [Server](https://rbxnet.australis.dev/docs/3.0/api/definitions#server) * [Client](https://rbxnet.australis.dev/docs/3.0/api/definitions#client) * [ServerDefinitionBuilder](https://rbxnet.australis.dev/docs/3.0/api/definitions#serverdefinitionbuildert) * [Get(name)](https://rbxnet.australis.dev/docs/3.0/api/definitions#getname) * [OnFunction(name, callback)](https://rbxnet.australis.dev/docs/3.0/api/definitions#onfunctionname-callback) * [OnEvent(name, callback)](https://rbxnet.australis.dev/docs/3.0/api/definitions#oneventname-callback) * [GetNamespace(name)](https://rbxnet.australis.dev/docs/3.0/api/definitions#getnamespacename) * [ClientDefinitionBuilder](https://rbxnet.australis.dev/docs/3.0/api/definitions#clientdefinitionbuildert) * [Get(name)](https://rbxnet.australis.dev/docs/3.0/api/definitions#getname-1) * [OnEvent(name, callback)](https://rbxnet.australis.dev/docs/3.0/api/definitions#oneventname-callback-1) * [OnFunction(name, callback)](https://rbxnet.australis.dev/docs/3.0/api/definitions#onfunctionname-callback-1) * [GetNamespace(name)](https://rbxnet.australis.dev/docs/3.0/api/definitions#getnamespacename-1) --- # Introduction | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/) ** (3.0.10). Version: 2.0.0 ![Net Logo](https://rbxnet.australis.dev/img/net2.svg) Roblox Networking (RbxNet) v2.0 =============================== [](https://www.npmjs.com/package/@rbxts/net) RbxNet is a _networking library_ for Roblox, built in TypeScript. It simplifies the creation and management of networking in Roblox. Features[#](https://rbxnet.australis.dev/docs/2.0/#features "Direct link to heading") -------------------------------------------------------------------------------------- * Creation and usage of remotes through "identifiers". Management of the remotes themselves are done by Net itself. * More explicit, contextual APIs. `Net.Server` for server-based API, and `Net.Client` for client-based API. * Ability for remote definitions through `Net.Definitions`. * Asynchronous functions - `Net.*.AsyncFunction`. No more pitfalls of regular remote functions. * Asynchronous callbacks and methods: because it's a roblox-ts library, it supports promises. * Middleware - Ability to add your own custom behaviours to remotes. Net comes with a runtime type checker, and a rate limiter middleware. * `Net.*.GameMessagingEvent` - interact with `MessagingService` like you would with regular remote events. Cross-server communication with the simple API. All the limitations are handled by Net. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/doc1.md) * [Features](https://rbxnet.australis.dev/docs/2.0/#features) --- # Logging | RbxNet Version: 3.0.10 [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/middleware/logger.md) --- # Writing custom middleware | RbxNet Version: 3.0.10 If you want to write a custom middleware (e.g. for logging, or other purposes), you must write a `Net.Middleware` compatible function. This is similar to a middleware function in [_rodux_](https://roblox.github.io/rodux/advanced/middleware/) . This function is given a callback `nextEvent`, and `instance` (the remote instance). It expects you to return a function, which is given the `sender`, and the `args` (arguments) after that, that were passed. This inner function should call and return `nextEvent` (if you want it to succeed) - or return nothing (if you don't want your remote to succeed with calling) * roblox-ts * luau Middleware Type Signature type NetMiddleware \= (next: (player: Player, ...args: CallArguments) \=> void, event: NetManagedInstance) \=> (sender: Player, ...args: PreviousCallArguments) \=> void; Copy export const MyMiddleware: Net.Middleware \= (nextMiddleware, instance) \=> { return (sender, ...args) \=> { return nextMiddleware(sender, ...args); }; }; Copy Luau Type type NetMiddleware \= (next: (player: Player, ...CallArguments) \-\> any, instance: NetManagedInstance) \-\> (player: Player, ...PreviousCallArguments) \-\> any Copy function MyMiddleware(next, instance) return function(player, ...) return next(player, ...) end end return { MyMiddleware \= MyMiddleware } Copy For example, if we want a specific remote to only be callable by _administrators_ in our game:- * roblox-ts * luau const GROUP\_ID \= 2664663; // Group id would go here export const AdministratorMiddleware: Net.Middleware \= (nextMiddleware, instance) \=> { return (sender, ...args) \=> { if (sender.GetRankInGroup(GROUP\_ID) \>= 250) { // This would continue the remote execution return nextMiddleware(sender, ...args); } // Otherwise the remote request is ignored }; }; Copy local GROUP\_ID \= 2664663 \-- group id would go here function MyMiddleware(next, instance) return function(sender, ...) if sender:GetRankInGroup(GROUP\_ID) \>= 250 then \-- This would continue the remote execution return next(sender, ...) end \-- Otherwise the remote request is ignored since the next middleware is never called end end return { MyMiddleware \= MyMiddleware } Copy The above middleware, when applied to a remote will only continue and call the callback/listener _if_ the `next`/`nextMiddleware` callbacks are called. Otherwise RbxNet will drop these requests. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/middleware/custom.md) --- # API Overview | RbxNet Version: 3.0.10 [Net.Server](https://rbxnet.australis.dev/docs/3.0/api/api/server) [#](https://rbxnet.australis.dev/docs/3.0/api#netserver "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- Base namespace for the server [Net.Client](https://rbxnet.australis.dev/docs/3.0/api/api/client) [#](https://rbxnet.australis.dev/docs/3.0/api#netclient "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- Base namespace for the client [Net.Definitions](https://rbxnet.australis.dev/docs/3.0/api/api/definitions) [#](https://rbxnet.australis.dev/docs/3.0/api#netdefinitions "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- The namespace for the [definitions](https://rbxnet.australis.dev/docs/3.0/api/definitions) feature. [Net.Middleware](https://rbxnet.australis.dev/docs/3.0/api/api/middleware) [#](https://rbxnet.australis.dev/docs/3.0/api#netmiddleware "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- The namespace for built in middleware [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/api/index.md) * [Net.Server](https://rbxnet.australis.dev/docs/3.0/api#netserver) * [Net.Client](https://rbxnet.australis.dev/docs/3.0/api#netclient) * [Net.Definitions](https://rbxnet.australis.dev/docs/3.0/api#netdefinitions) * [Net.Middleware](https://rbxnet.australis.dev/docs/3.0/api#netmiddleware) --- # Install for TypeScript | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/install) ** (3.0.10). Version: 2.1.5 The TypeScript version of RbxNet requires knowledge and usage of [roblox-ts](https://roblox-ts.com/) . Install via Node Package Manager (NPM)[#](https://rbxnet.australis.dev/docs/2.1/install/#install-via-node-package-manager-npm "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------------- RbxNet is available on NPM. To install it to your roblox-ts project, type the following in command line/terminal npm install @rbxts/net Copy Once you have the module installed, you can then use it in code by importing it as such: import Net from "@rbxts/net"; Copy Install from GitHub[#](https://rbxnet.australis.dev/docs/2.1/install/#install-from-github "Direct link to heading") -------------------------------------------------------------------------------------------------------------------- This is the option to use if you're wanting to use the latest master build of rbx-net. It's recommended though you use the above NPM option. npm install github:roblox-aurora/rbx-net Copy Once you have the module installed, you can then use it in code by importing it as such: import Net from "@rbxts/net"; Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/install.md) * [Install via Node Package Manager (NPM)](https://rbxnet.australis.dev/docs/2.1/install/#install-via-node-package-manager-npm) * [Install from GitHub](https://rbxnet.australis.dev/docs/2.1/install/#install-from-github) --- # Install for TypeScript | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/install) ** (3.0.10). Version: 2.0.0 The TypeScript version of RbxNet requires knowledge and usage of [roblox-ts](https://roblox-ts.com/) . From NPM[#](https://rbxnet.australis.dev/docs/2.0/install/#from-npm "Direct link to heading") ---------------------------------------------------------------------------------------------- RbxNet is available on NPM. To install it to your roblox-ts project, type the following in command line/terminal npm install @rbxts/net@2.0 Copy Once you have the module installed, you can then use it in code by importing it as such: import Net from "@rbxts/net"; Copy From GitHub[#](https://rbxnet.australis.dev/docs/2.0/install/#from-github "Direct link to heading") ---------------------------------------------------------------------------------------------------- This is the option to use if you're wanting to use the latest master build of rbx-net. It's recommended though you use the above NPM option. npm install github:roblox-aurora/rbx-net Copy Once you have the module installed, you can then use it in code by importing it as such: import Net from "@rbxts/net"; Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/install.md) * [From NPM](https://rbxnet.australis.dev/docs/2.0/install/#from-npm) * [From GitHub](https://rbxnet.australis.dev/docs/2.0/install/#from-github) --- # Install for Luau | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/install-luau) ** (3.0.10). Version: 2.1.5 Depending on your stack for Roblox, you might want to either use the [Rojo](https://rbxnet.australis.dev/docs/2.1/install-luau/#via-rojo) step or the [Studio](https://rbxnet.australis.dev/docs/2.1/install-luau/#via-studio) step. If you don't know what _Rojo_ is, use the Studio step. Via Rojo[#](https://rbxnet.australis.dev/docs/2.1/install-luau/#via-rojo "Direct link to heading") --------------------------------------------------------------------------------------------------- The following steps require knowledge and use of [rojo](https://rojo.space/) . If you're not using rojo, look at [studio](https://rbxnet.australis.dev/docs/2.1/install-luau/#via-studio) instructions. ### Install via Wally[#](https://rbxnet.australis.dev/docs/2.1/install-luau/#install-via-wally "Direct link to heading") First, if you haven't already - [Install Wally](https://github.com/UpliftGames/wally) . Then, in your `wally.toml` file for your project, put under `dependencies`: \# ... \[dependencies\] \# ... Net = "vorlias/net@2.1.4" Copy Then run wally install Copy ### Manually install via git submodules[#](https://rbxnet.australis.dev/docs/2.1/install-luau/#manually-install-via-git-submodules "Direct link to heading") ##### caution This method, while works... isn't the nicest way to do it. Execute in powershell or bash: git submodule add https://github.com/roblox-aurora/rbx-net -b luau submodules/Net Copy Then you can include it in your `*.project.json` file like so: // ... "ReplicatedStorage": { // ... "Net": { "$path": "submodules/Net/dist" } // ... }, // ... Copy And now you can use rbx-net like so: local Net = require(game:GetService("ReplicatedStorage").Net) Copy Via Studio[#](https://rbxnet.australis.dev/docs/2.1/install-luau/#via-studio "Direct link to heading") ------------------------------------------------------------------------------------------------------- ### RBXMX model file[#](https://rbxnet.australis.dev/docs/2.1/install-luau/#rbxmx-model-file "Direct link to heading") Releases can be found [here](https://github.com/roblox-aurora/rbx-net/releases) . Download the appropriate `.rbxmx` file under the `Assets` dropdown, then drag it into studio. Ensure the library is under `ReplicatedStorage` so it can be used by all your code. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/install-lua.md) * [Via Rojo](https://rbxnet.australis.dev/docs/2.1/install-luau/#via-rojo) * [Install via Wally](https://rbxnet.australis.dev/docs/2.1/install-luau/#install-via-wally) * [Manually install via git submodules](https://rbxnet.australis.dev/docs/2.1/install-luau/#manually-install-via-git-submodules) * [Via Studio](https://rbxnet.australis.dev/docs/2.1/install-luau/#via-studio) * [RBXMX model file](https://rbxnet.australis.dev/docs/2.1/install-luau/#rbxmx-model-file) --- # Getting started | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/definitions) ** (3.0.10). Version: 2.1.5 What are definitions?[#](https://rbxnet.australis.dev/docs/2.1/definitions/#what-are-definitions "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------- Definitions are a sort of "blueprint" for all the networking related objects in your game or library. It's a single source of truth in which all the code in your game can access remotes through, to handle your game or library's networking. Creating a definition script[#](https://rbxnet.australis.dev/docs/2.1/definitions/#creating-a-definition-script "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------------ To use definitions, you will need to create a script that is somewhere in `ReplicatedStorage` (or inside the library itself if you're doing it for a library). It needs to be accessible by both server scripts and client scripts. The basic declaration of a definition script, is the following: * roblox-ts * luau shared/remotes.ts import Net from "@rbxts/net"; const Remotes \= Net.Definitions.Create({ // Definitions for the actual remotes will go here }); export \= Remotes; Copy src/shared/remotes.lua local Net = require(ReplicatedStorage.Net) local Remotes = Net.Definitions.Create({ \-- Definitions for the actual remotes will go here }) return Remotes Copy Then simply, you can import the module from your code, and use the definitions API to get the remotes [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/definitions/00-overview.md) * [What are definitions?](https://rbxnet.australis.dev/docs/2.1/definitions/#what-are-definitions) * [Creating a definition script](https://rbxnet.australis.dev/docs/2.1/definitions/#creating-a-definition-script) --- # Using your definitions | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/definitions/using) ** (3.0.10). Version: 2.1.5 Say that we have our example definition file here: * roblox-ts * luau shared/remotes.ts import { Definitions } from "@rbxts/net"; const Remotes \= Definitions.Create({ GetPlayerInventory: Definitions.ServerAsyncFunction<() \=> SerializedPlayerInventory\>(), GetPlayerEquipped: Definitions.ServerAsyncFunction<() \=> SerializedPlayerEquipped\>(), PlayerInventoryUpdated: Definitions.ServerToClientEvent<\[event: InventoryUpdatedEvent\]\>(), PlayerEquippedUpdated: Definitions.ServerToClientEvent<\[event: EquippedUpdatedEvent\]\>(), PlayerUnequipItem: Definitions.ClientToServerEvent<\[itemId: number\]\>(), PlayerEquipItem: Definitions.ClientToServerEvent<\[itemId: number\]\>(), }); export \= Remotes; Copy src/shared/remotes.lua local Net = require(ReplicatedStorage.Net) local Remotes = Net.Definitions.Create({ GetPlayerInventory = Net.Definitions.ServerFunction(), GetPlayerEquipped = Net.Definitions.ServerFunction(), PlayerInventoryUpdated = Net.Definitions.ServerToClientEvent(), PlayerEquippedUpdated = Net.Definitions.ServerToClientEvent(), PlayerUnequipItem = Net.Definitions.ClientToServerEvent(), PlayerEquipItem = Net.Definitions.ClientToServerEvent(), }) return Remotes Copy How would we approach using this to actually be able to send messages between the server and client? Usage from the server[#](https://rbxnet.australis.dev/docs/2.1/definitions/using/#usage-from-the-server "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------- * roblox-ts * luau server/main.server.ts import Remotes from "shared/remotes"; Copy src/server/main.server.lua local Remotes = require(ReplicatedStorage.Shared.Remotes) Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/definitions/02-implementation.md) * [Usage from the server](https://rbxnet.australis.dev/docs/2.1/definitions/using/#usage-from-the-server) --- # Creating a definition | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/definitions/starting) ** (3.0.10). Version: 2.1.5 In RbxNet, there are three categories of remote objects: * **Event** - This is analogous to a `RemoteEvent`. This is what is used if you want to send an event (like an action) to the server or a player. * **AsyncFunction** - This is _like_ a `RemoteFunction`, but uses `RemoteEvent` internally. The difference with this and `Function` is that `AsyncFunction` _will_ handle time outs and runs completely asynchronously. (meaning it wont yield code) If there is no response from the reciever, it will reject. * **Function** - This is analogous to a `RemoteFunction`. However unlike a regular `RemoteFunction` this does not allow you to call a client. This is for security reasons discussed [here](https://github.com/roblox-aurora/rbx-net/issues/13) Defining Events & Functions[#](https://rbxnet.australis.dev/docs/2.1/definitions/starting/#defining-events--functions "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------------------ Given the above knowledge, we can then apply that to our remote definition script. There are the following functions under `Net.Definitions` for creating definitions for the three categories we have above. The API for each type of definition is explicit so it is easy to understand what each defined remote does. ### The different types of definitions[#](https://rbxnet.australis.dev/docs/2.1/definitions/starting/#the-different-types-of-definitions "Direct link to heading") * Event * **`Net.Definitions.ServerToClientEvent`** - Defines an event in which the server sends an event to one or many clients * **`Net.Definitions.ClientToServerEvent`** - Defines an event in which the client send events to the server * **`Net.Definitions.BidirectionalEvent`** - Defines an event in which both the server can send an event to one or many clients, and also the clients can send events to the server. _This should only be used in cases where it's required_. * AsyncFunction * **`Net.Definitions.ServerAsyncFunction`** - Defines an async function which exists on the server, and can be called by clients. The returned result will be recieved on the client as a promise. * **`Net.Definitions.ClientAsyncFunction`** - Defines an async function which exists on the client, and can be called by the server. The returned result will be recieved on the server as a promise. * Function * **`Net.Definitions.ServerFunction`** - Defines a synchronous function which exists on the server, and can be called by clients ### Defining remotes[#](https://rbxnet.australis.dev/docs/2.1/definitions/starting/#defining-remotes "Direct link to heading") With the above knowledge, we can create a few example definitions. Say I would like a use case like the following ![](data:image/png;base64,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) * roblox-ts * luau shared/remotes.ts import { Definitions } from "@rbxts/net"; const Remotes \= Definitions.Create({ GetPlayerInventory: Definitions.ServerAsyncFunction<() \=> SerializedPlayerInventory\>(), GetPlayerEquipped: Definitions.ServerAsyncFunction<() \=> SerializedPlayerEquipped\>(), PlayerInventoryUpdated: Definitions.ServerToClientEvent<\[event: InventoryUpdatedEvent\]\>(), PlayerEquippedUpdated: Definitions.ServerToClientEvent<\[event: EquippedUpdatedEvent\]\>(), PlayerUnequipItem: Definitions.ClientToServerEvent<\[itemId: number\]\>(), PlayerEquipItem: Definitions.ClientToServerEvent<\[itemId: number\]\>(), }); export \= Remotes; Copy src/shared/remotes.lua local Net = require(ReplicatedStorage.Net) local Remotes = Net.Definitions.Create({ GetPlayerInventory = Net.Definitions.ServerFunction(), GetPlayerEquipped = Net.Definitions.ServerFunction(), PlayerInventoryUpdated = Net.Definitions.ServerToClientEvent(), PlayerEquippedUpdated = Net.Definitions.ServerToClientEvent(), PlayerUnequipItem = Net.Definitions.ClientToServerEvent(), PlayerEquipItem = Net.Definitions.ClientToServerEvent(), }) return Remotes Copy Straight away you can see it's quite easy to know what remote does what. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/definitions/01-starting.md) * [Defining Events & Functions](https://rbxnet.australis.dev/docs/2.1/definitions/starting/#defining-events--functions) * [The different types of definitions](https://rbxnet.australis.dev/docs/2.1/definitions/starting/#the-different-types-of-definitions) * [Defining remotes](https://rbxnet.australis.dev/docs/2.1/definitions/starting/#defining-remotes) --- # Using Compile Time Remote IDs | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/uuid) ** (3.0.10). Version: 2.1.5 ##### TypeScript Only This functionality is only available to roblox-ts users. This is not possible in regular Luau. A feature that can be leveraged with the power of the roblox-ts compiler, is a thing referred to as "Remote Ids". This is a way to throw off any identifying information about your remotes to any external parties. If used correctly it should make it quite hard to make exploit tools for your game, and throw off most exploiters. ##### caution It is not an anti-exploit solution, but a [good piece of cheese](https://utkusen.com/blog/security-by-obscurity-is-underrated.html) in preventing exploits. You _should always_ secure your remotes yourself, using things like the [runtime type checking middleware](https://rbxnet.australis.dev/docs/2.0/middleware/types) . Doesn't hurt to add another layer of cheese. Getting started[#](https://rbxnet.australis.dev/docs/2.1/uuid/#getting-started "Direct link to heading") --------------------------------------------------------------------------------------------------------- To start using Remote Ids, first install the Remote Id generation tool: npm install -g roblox-ts-net-idgen Copy Then, create a new `remoteIds.id.json` file inside your project. It doesn't have to be called `remoteIds`, but for this example that's what we're doing. As long as it ends with `.id.json`. shared/remoteIds.id.json { "Name": "RemoteId", "IDs": \[\ \ \] } Copy The `Name` field is the outputted name of the `const enum`, and the `IDs` will be the IDs you have for your remotes. Now lets add some example remote ids shared/remoteIds.id.json { "Name": "RemoteId", "IDs": \[\ \ "PrintMessage",\ \ "MakeHello"\ \ \] } Copy Now that we have some remote ids, we need to generate the `type declaration` file. Run the command in your console: rbxnid Copy A new `remoteId.d.ts` file should have been generated, and should look like the following: shared/remoteId.d.ts export const enum RemoteId { PrintMessage \= "cbf11f23-ed6e-43f6-8750-fce7c6558ae4", MakeHello \= "ffa61bfe-d8ba-4c82-a7eb-3dd36b133184" } Copy These IDs will change every time you run the `rbxnid` command. It's recommended you do this as part of your build process, so each new build of your game has an entirely new set of IDs. This will ensure that it's difficult to make any specific exploit tools for your game. Usage[#](https://rbxnet.australis.dev/docs/2.1/uuid/#usage "Direct link to heading") ------------------------------------------------------------------------------------- Then when you have the RemoteIds, you can use them in place where you'd normally supply a remote id: import Net from "@rbxts/net"; import { RemoteId } from "shared/remoteId"; const ExampleUsage \= new Net.Server.Event(RemoteId.PrintMessage); Copy This will end up compiling to compiled code \--- ... roblox-ts imports local ExampleUsage = Net.Server.Event.new("cbf11f23-ed6e-43f6-8750-fce7c6558ae4") Copy ### Using with Definitions[#](https://rbxnet.australis.dev/docs/2.1/uuid/#using-with-definitions "Direct link to heading") Using remote ids with definitions is straightforward. import Net from "@rbxts/net"; import { RemoteId } from "shared/remoteId"; const Remotes \= Net.Definitions.Create({ \[RemoteId.PrintMessage\]: Net.Definitions.Event<\[message: string\]\>(), \[RemoteId.MakeHello\]: Net.Definitions.AsyncFunction<(message: string) \=> string\>() }); export \= Remotes; Copy Which should compile to the following: compiled code \-- ... roblox-ts imports local Remotes = Net.Definitions.Create({ \["cbf11f23-ed6e-43f6-8750-fce7c6558ae4"\] = Net.Definitions.Event(), \["ffa61bfe-d8ba-4c82-a7eb-3dd36b133184"\] = Net.Definitions.AsyncFunction() }) \-- .. exports Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/guides/uuid.md) * [Getting started](https://rbxnet.australis.dev/docs/2.1/uuid/#getting-started) * [Usage](https://rbxnet.australis.dev/docs/2.1/uuid/#usage) * [Using with Definitions](https://rbxnet.australis.dev/docs/2.1/uuid/#using-with-definitions) --- # Runtime Type Checking | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/middleware/types) ** (3.0.10). Version: 2.1.5 It's important when you recieve events or calls from the server that you ensure the types are correct, otherwise unwanted errors may pop up. If you want to ensure the types you're recieving from the client _are_ the types you're expecting, you can use the [`Net.Middleware.TypeChecking`](https://rbxnet.australis.dev/docs/2.1/api/middleware#typechecking) middleware. This middleware just takes type checking functions. Using a library like `t`[#](https://rbxnet.australis.dev/docs/2.1/middleware/types/#using-a-library-like-t "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------- The rate limiter middleware is created as such: * roblox-ts * luau Net.Middleware.TypeCheck(t.string) Copy Net.Middleware.TypeCheck(t.string) Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/middleware/typecheck.md) * [Using a library like `t`](https://rbxnet.australis.dev/docs/2.1/middleware/types/#using-a-library-like-t) --- # Wrapping Custom Player Objects | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/custom-player-objects) ** (3.0.10). Version: 2.1.5 How one might do it[#](https://rbxnet.australis.dev/docs/2.1/custom-player-objects/#how-one-might-do-it "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------- A common pattern when using remotes - on the server - is to require casting a player to an object representation of the player. This may come as the following sort of situation: * roblox-ts * luau import PlayerService from "server/Services/PlayerService"; const PlayerEquipItem \= new Net.Server.Event<\[itemId: number\]\>("PlayerEquipItem") PlayerEquipItem.Connect((player, itemId) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { entity.EquipItem(itemId); } }) const PlayerUnequipItem \= new Net.Server.Event<\[itemId: number\]\>("PlayerUnequipItem") PlayerUnequipItem.Connect((player, itemId) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { entity.UnequipItem(itemId); } }) const GetPlayerEquipped \= new Net.Server.AsyncFunction("GetPlayerEquipped") GetPlayerEquipped.SetCallback((player) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { return entity.GetEquippedItems(); } }) Copy local PlayerService = require(ServerScriptService.Services.PlayerService) local PlayerEquipItem = Net.Server.Event.new("PlayerEquipItem") PlayerEquipItem:Connect(function (player, itemId) local entity = PlayerService:GetEntity(player) if entity then entity:EquipItem(itemId) end end) local PlayerUnequipItem = Net.Server.Event.new("PlayerUnequipItem") PlayerUnequipItem:Connect(function (player, itemId) local entity = PlayerService:GetEntity(player) if entity then entity:UnequipItem(itemId) end end) local GetPlayerEquipped = Net.Server.AsyncFunction.new("GetPlayerEquipped") GetPlayerEquipped:SetCallback(function(player) local entity = PlayerService:GetEntity(player) if entity then return entity:GetEquippedItems() end end) Copy As you might have noticed, there's some repeated code where we're repetitively having to grab the player entity here in place of the player. We can instead use what's called a _wrapper_ to do this for us and make it as if we were connecting directly to the remote and it had the entity as the player argument rather than a player. Using a wrapper[#](https://rbxnet.australis.dev/docs/2.1/custom-player-objects/#using-a-wrapper "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------- We can define a `withPlayerEntity` wrapper, which will achieve what we're doing above in each remote separately. This is the recommended method when augmenting the player argument as it's the safest method and guaranteed to run after all the middleware. * roblox-ts * luau server/Wrappers/withPlayerEntity.ts import PlayerService from "server/Services/PlayerService"; import PlayerEntity from "server/Classes/PlayerEntity"; export default function withPlayerEntity, R \= void\>( fn: (playerEntity: PlayerEntity, ...args: T) \=> R, ) { return (player: Player, ...args: T) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { return fn(entity, ...args); } }; } Copy src/server/Wrappers/withPlayerEntity.lua local PlayerService = require(ServerScriptService.Services.PlayerService) local function withPlayerEntity(fn) return function (player, ...) local entity = playerService:GetEntity(player) if entity then return fn(entity, ...) end end end return withPlayerEntity Copy Then we can apply this to the code above. * roblox-ts * luau import PlayerService from "server/Services/PlayerService"; import withPlayerEntity from "server/Wrappers/withPlayerEntity"; const PlayerEquipItem \= new Net.Server.Event<\[itemId: number\]\>("PlayerEquipItem") PlayerEquipItem.Connect( withPlayerEntity((entity, itemId) \=> { entity.EquipItem(itemId); }) ); const PlayerUnequipItem \= new Net.Server.Event<\[itemId: number\]\>("PlayerUnequipItem") PlayerUnequipItem.Connect((player, itemId) \=> { withPlayerEntity((entity, itemId) \=> { entity.UnequipItem(itemId); }) }) const GetPlayerEquipped \= new Net.Server.AsyncFunction("GetPlayerEquipped") GetPlayerEquipped.SetCallback( withPlayerEntity((player) \=> { return entity.GetEquippedItems(); }) ) Copy local PlayerService = require(ServerScriptService.Services.PlayerService) local withPlayerEntity = require(ServerScriptService.Wrappers.withPlayerEntity) local PlayerEquipItem = Net.Server.Event.new("PlayerEquipItem") PlayerEquipItem:Connect( withPlayerEntity(function (entity, itemId) entity:EquipItem(itemId) end) ) local PlayerUnequipItem = Net.Server.Event.new("PlayerUnequipItem") PlayerUnequipItem:Connect( withPlayerEntity(function (player, itemId) entity:UnequipItem(itemId) end) ) local GetPlayerEquipped = Net.Server.AsyncFunction.new("GetPlayerEquipped") GetPlayerEquipped:SetCallback( withPlayerEntity(function(player) return entity:GetEquippedItems() end) ) Copy And as you can see, this reduces repetitive code and gives us the `PlayerEntity` object to work with. Simple as that. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/guides/connect-wrapper.md) * [How one might do it](https://rbxnet.australis.dev/docs/2.1/custom-player-objects/#how-one-might-do-it) * [Using a wrapper](https://rbxnet.australis.dev/docs/2.1/custom-player-objects/#using-a-wrapper) --- # Rate limiting your remotes | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/middleware/rate-limit) ** (3.0.10). Version: 2.1.5 Your event or AsyncFunction may perform an intensive task that you don't want players to be able to invoke every second (and possibly crash your game) A way you can get around this is by using the [`Net.Middleware.RateLimit`](https://rbxnet.australis.dev/docs/2.1/api/middleware#ratelimit) middleware. This is a built in. Limiting to a certain amount of requests[#](https://rbxnet.australis.dev/docs/2.1/middleware/rate-limit/#limiting-to-a-certain-amount-of-requests "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The rate limiter middleware is created as such: * roblox-ts * luau Net.Middleware.RateLimit({ MaxRequestsPerMinute: 1 // This can be the amount of requests you want to limit per minute }) Copy Net.Middleware.RateLimit({ MaxRequestsPerMinute = 1 -- This can be the amount of requests you want to limit per minute }) Copy Then you pass it to a constructor for a server object, or a definition: * roblox-ts * luau Object const Example \= new Net.Server.AsyncFunction("Example", \[\ \ Net.Middleware.RateLimit({\ \ MaxRequestsPerMinute: 1\ \ })\ \ \]) Copy Definition const Remotes \= Net.Definitions.Create({ Example: Net.Definitions.AsyncFunction(\[\ \ Net.Middleware.RateLimit({\ \ MaxRequestsPerMinute: 1\ \ })\ \ \]) }) Copy Object local Example = Net.Server.AsyncFunction.new("Example", { Net.Middleware.RateLimit({ MaxRequestsPerMinute = 1 }) }) Copy Definition local Remotes = Net.Definitions.Create({ Example = Net.Definitions.AsyncFunction({ Net.Middleware.RateLimit({ MaxRequestsPerMinute: 1 }) }) }) Copy Custom Error Handling[#](https://rbxnet.australis.dev/docs/2.1/middleware/rate-limit/#custom-error-handling "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------- When the rate limit is reached, it will run the error handler. By default this is set to a function which displays a warning on the server: export function rateLimitWarningHandler(error: RateLimitError) { warn("\[rbx-net\]", error.Message); } Copy However, if you want to send this to something like analytics, you can provide your own error handler: * roblox-ts * luau function analyticRateLimitError(error: RateLimitError) { AnalyticsService.Error(error.Message); // this is just an example } Copy Object const Example \= new Net.Server.AsyncFunction("Example", \[\ \ Net.Middleware.RateLimit({\ \ MaxRequestsPerMinute: 1,\ \ ErrorHandler: analyticRateLimitError\ \ })\ \ \]) Copy Definition const Remotes \= Net.Definitions.Create({ Example: Net.Definitions.AsyncFunction(\[\ \ Net.Middleware.RateLimit({\ \ MaxRequestsPerMinute: 1,\ \ ErrorHandler: analyticRateLimitError\ \ })\ \ \]) }) Copy local function analyticRateLimitError(error) AnalyticsService:Error(error.Message) -- this is just an example end Copy Object local Example = Net.Server.AsyncFunction.new("Example", { Net.Middleware.RateLimit({ MaxRequestsPerMinute = 1, ErrorHandler = analyticRateLimitError }) }) Copy Definition local Remotes = Net.Definitions.Create({ Example = Net.Definitions.AsyncFunction({ Net.Middleware.RateLimit({ MaxRequestsPerMinute: 1, ErrorHandler = analyticRateLimitError }) }) }) Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/middleware/ratelimit.md) * [Limiting to a certain amount of requests](https://rbxnet.australis.dev/docs/2.1/middleware/rate-limit/#limiting-to-a-certain-amount-of-requests) * [Custom Error Handling](https://rbxnet.australis.dev/docs/2.1/middleware/rate-limit/#custom-error-handling) --- # API Overview | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/api) ** (3.0.10). Version: 2.1.5 [Net.Server](https://rbxnet.australis.dev/docs/2.1/api/server) [#](https://rbxnet.australis.dev/docs/2.1/api/#netserver "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------- Base namespace for the server [Net.Client](https://rbxnet.australis.dev/docs/2.1/api/client) [#](https://rbxnet.australis.dev/docs/2.1/api/#netclient "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------- Base namespace for the client [Net.Definitions](https://rbxnet.australis.dev/docs/2.1/api/definitions) [#](https://rbxnet.australis.dev/docs/2.1/api/#netdefinitions "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- The namespace for the [definitions](https://rbxnet.australis.dev/docs/2.1/definitions) feature. [Net.Middleware](https://rbxnet.australis.dev/docs/2.1/api/middleware) [#](https://rbxnet.australis.dev/docs/2.1/api/#netmiddleware "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------- The namespace for built in middleware [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/api/index.md) * [Net.Server](https://rbxnet.australis.dev/docs/2.1/api/#netserver) * [Net.Client](https://rbxnet.australis.dev/docs/2.1/api/#netclient) * [Net.Definitions](https://rbxnet.australis.dev/docs/2.1/api/#netdefinitions) * [Net.Middleware](https://rbxnet.australis.dev/docs/2.1/api/#netmiddleware) --- # Net.Server Namespace | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/api/server) ** (3.0.10). Version: 2.1.5 This contains all the server-related code relating to Net Event[#](https://rbxnet.australis.dev/docs/2.1/api/server/#event "Direct link to heading") ------------------------------------------------------------------------------------------- class ServerEvent { constructor(name: string, middleware?: Middleware); GetInstance(): RemoteEvent; Connect(callback: (player: Player, ...args: ConnectArgs) \=> void): RBXScriptConnection; SendToAllPlayers(...args: CallArgs): void; SendToAllPlayersExcept(blacklist: Player | Player\[\], ...args: CallArgs): void; SendToPlayer(player: Player, ...args: CallArgs): void; SendToPlayers(players: Player\[\], ...args: CallArgs): void; } Copy ### GetInstance[#](https://rbxnet.australis.dev/docs/2.1/api/server/#getinstance "Direct link to heading") ### Connect[#](https://rbxnet.australis.dev/docs/2.1/api/server/#connect "Direct link to heading") ### SendToAllPlayers[#](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoallplayers "Direct link to heading") ### SendToAllPlayersExcept[#](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoallplayersexcept "Direct link to heading") ### SendToPlayer[#](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoplayer "Direct link to heading") ### SendToPlayers[#](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoplayers "Direct link to heading") Function[#](https://rbxnet.australis.dev/docs/2.1/api/server/#function "Direct link to heading") ------------------------------------------------------------------------------------------------- class ServerFunction { constructor(name: string, middleware?: Middleware); GetInstance(): RemoteFunction; SetCallback(callback: (player: Player, ...args: CallbackArgs) \=> Returns): void; } Copy ### GetInstance[#](https://rbxnet.australis.dev/docs/2.1/api/server/#getinstance-1 "Direct link to heading") ### SetCallback[#](https://rbxnet.australis.dev/docs/2.1/api/server/#setcallback "Direct link to heading") AsyncFunction[#](https://rbxnet.australis.dev/docs/2.1/api/server/#asyncfunction "Direct link to heading") ----------------------------------------------------------------------------------------------------------- class ServerAsyncFunction { constructor(name: string, middleware?: Middleware); GetInstance(): RemoteEvent; SetCallback(callback: (player: Player, ...args: CallbackArgs) \=> any): void; CallPlayerAsync(player: Player, ...args: CallArgs): Promise; } Copy ### GetInstance[#](https://rbxnet.australis.dev/docs/2.1/api/server/#getinstance-2 "Direct link to heading") ### SetCallback[#](https://rbxnet.australis.dev/docs/2.1/api/server/#setcallback-1 "Direct link to heading") ### CallPlayerAsync[#](https://rbxnet.australis.dev/docs/2.1/api/server/#callplayerasync "Direct link to heading") CrossServerEvent[#](https://rbxnet.australis.dev/docs/2.1/api/server/#crossserverevent "Direct link to heading") ----------------------------------------------------------------------------------------------------------------- class CrossServerEvent { constructor(name: string); SendToAllServers(...args: unknown\[\]): void; SendToServer(jobId: string, ...args: unknown\[\]): void; SendToPlayer(userId: number, ...args: unknown\[\]): void; SendToPlayers(userIds: number\[\], ...args: unknown\[\]): void; Disconnect(): void; } Copy ### SendToAllServers[#](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoallservers "Direct link to heading") ### SendToServer[#](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoserver "Direct link to heading") ### SendToPlayer[#](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoplayer-1 "Direct link to heading") ### SendToPlayers[#](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoplayers-1 "Direct link to heading") ### Disconnect[#](https://rbxnet.australis.dev/docs/2.1/api/server/#disconnect "Direct link to heading") [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/api/net-server.md) * [Event](https://rbxnet.australis.dev/docs/2.1/api/server/#event) * [GetInstance](https://rbxnet.australis.dev/docs/2.1/api/server/#getinstance) * [Connect](https://rbxnet.australis.dev/docs/2.1/api/server/#connect) * [SendToAllPlayers](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoallplayers) * [SendToAllPlayersExcept](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoallplayersexcept) * [SendToPlayer](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoplayer) * [SendToPlayers](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoplayers) * [Function](https://rbxnet.australis.dev/docs/2.1/api/server/#function) * [GetInstance](https://rbxnet.australis.dev/docs/2.1/api/server/#getinstance-1) * [SetCallback](https://rbxnet.australis.dev/docs/2.1/api/server/#setcallback) * [AsyncFunction](https://rbxnet.australis.dev/docs/2.1/api/server/#asyncfunction) * [GetInstance](https://rbxnet.australis.dev/docs/2.1/api/server/#getinstance-2) * [SetCallback](https://rbxnet.australis.dev/docs/2.1/api/server/#setcallback-1) * [CallPlayerAsync](https://rbxnet.australis.dev/docs/2.1/api/server/#callplayerasync) * [CrossServerEvent](https://rbxnet.australis.dev/docs/2.1/api/server/#crossserverevent) * [SendToAllServers](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoallservers) * [SendToServer](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoserver) * [SendToPlayer](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoplayer-1) * [SendToPlayers](https://rbxnet.australis.dev/docs/2.1/api/server/#sendtoplayers-1) * [Disconnect](https://rbxnet.australis.dev/docs/2.1/api/server/#disconnect) --- # Net.Client Namespace | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/api/client) ** (3.0.10). Version: 2.1.5 This contains all the client-related code relating to Net Event[#](https://rbxnet.australis.dev/docs/2.1/api/client/#event "Direct link to heading") ------------------------------------------------------------------------------------------- class ClientEvent { constructor(name: string); SendToServer(...args: CallArguments): void; Connect(callback: (...args: ConnectArgs) \=> void): RBXScriptConnection; } Copy ### SendToServer[#](https://rbxnet.australis.dev/docs/2.1/api/client/#sendtoserver "Direct link to heading") ### Connect[#](https://rbxnet.australis.dev/docs/2.1/api/client/#connect "Direct link to heading") Function[#](https://rbxnet.australis.dev/docs/2.1/api/client/#function "Direct link to heading") ------------------------------------------------------------------------------------------------- class ClientFunction { constructor(name: string); CallServerAsync(...args: CallArgs): Promise; } Copy ### CallServerAsync[#](https://rbxnet.australis.dev/docs/2.1/api/client/#callserverasync "Direct link to heading") AsyncFunction[#](https://rbxnet.australis.dev/docs/2.1/api/client/#asyncfunction "Direct link to heading") ----------------------------------------------------------------------------------------------------------- class ClientAsyncFunction { constructor(name: string); CallServerAsync(...args: CallArgs): Promise; SetCallback(callback: (...args: CallbackArgs) \=> any): void; SetCallTimeout(timeout: number): void; GetCallTimeout(): number; } Copy ### CallServerAsync[#](https://rbxnet.australis.dev/docs/2.1/api/client/#callserverasync-1 "Direct link to heading") ### SetCallback[#](https://rbxnet.australis.dev/docs/2.1/api/client/#setcallback "Direct link to heading") ### SetCallTimeout[#](https://rbxnet.australis.dev/docs/2.1/api/client/#setcalltimeout "Direct link to heading") ### GetCalllTimeout[#](https://rbxnet.australis.dev/docs/2.1/api/client/#getcallltimeout "Direct link to heading") CrossServerEvent[#](https://rbxnet.australis.dev/docs/2.1/api/client/#crossserverevent "Direct link to heading") ----------------------------------------------------------------------------------------------------------------- class CrossServerEvent { constructor(name: string); Connect(callback: (...args: unknown\[\]) \=> void): void; } Copy ### Connect[#](https://rbxnet.australis.dev/docs/2.1/api/client/#connect-1 "Direct link to heading") [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/api/net-client.md) * [Event](https://rbxnet.australis.dev/docs/2.1/api/client/#event) * [SendToServer](https://rbxnet.australis.dev/docs/2.1/api/client/#sendtoserver) * [Connect](https://rbxnet.australis.dev/docs/2.1/api/client/#connect) * [Function](https://rbxnet.australis.dev/docs/2.1/api/client/#function) * [CallServerAsync](https://rbxnet.australis.dev/docs/2.1/api/client/#callserverasync) * [AsyncFunction](https://rbxnet.australis.dev/docs/2.1/api/client/#asyncfunction) * [CallServerAsync](https://rbxnet.australis.dev/docs/2.1/api/client/#callserverasync-1) * [SetCallback](https://rbxnet.australis.dev/docs/2.1/api/client/#setcallback) * [SetCallTimeout](https://rbxnet.australis.dev/docs/2.1/api/client/#setcalltimeout) * [GetCalllTimeout](https://rbxnet.australis.dev/docs/2.1/api/client/#getcallltimeout) * [CrossServerEvent](https://rbxnet.australis.dev/docs/2.1/api/client/#crossserverevent) * [Connect](https://rbxnet.australis.dev/docs/2.1/api/client/#connect-1) --- # Using namespaces | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/definitions/namespacing) ** (3.0.10). Version: 2.1.5 [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/definitions/03-namespacing.md) --- # Logging | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/middleware/logging) ** (3.0.10). Version: 2.1.5 [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/middleware/logger.md) --- # Writing custom middleware | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/middleware/custom) ** (3.0.10). Version: 2.1.5 [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/middleware/custom.md) --- # Net.Definitions Namespace | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/api/definitions) ** (3.0.10). Version: 2.1.5 This namespace is for the Definitions feature. ### Definitions.Create(definitions)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionscreatedefinitions "Direct link to heading") function Create( remotes: T, globalMiddleware?: Net.GlobalMiddleware ): DefinitionBuilders Copy Function * Parameters * `remotes` An object of remote definitions. See [definitions](https://rbxnet.australis.dev/docs/2.1/definitions#definitions-oh-my) for usage. * `globalMiddleware` (optional) A collection of _global middleware_ to apply to all remotes in this definition * Returns a [DefinitionsCreateResult](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionscreateresultt) Example shared/remotes.ts import Net from "@rbxts/net"; const MyDefinitions \= Net.Definitions.Create({ TestRemote: Net.Definitions.AsyncFunction<(name: string) \=> boolean\>() }); Copy ### Definitions.ServerFunction(...)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsserverfunctionserver "Direct link to heading") Definition function for creating a `FunctionDefinition` ### Definitions.ServerToClientEvent(...)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsservertoclienteventserverargs "Direct link to heading") Definition function for creating an `ServerEventDeclaration` ### Definitions.ClientToServerEvent(...)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsclienttoservereventclientargs "Direct link to heading") Definition function for creating an `ClientEventDeclaration` ### Definitions.BidirectionalEvent(...)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsbidirectionaleventserverargs-clientargs "Direct link to heading") Definition function for creating an `BidirectionalEventDeclaration` ### Definitions.ServerAsyncFunction(...)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsserverasyncfunctionserver "Direct link to heading") Definition function for creating an `ServerAsyncFunctionDefinition` ### Definitions.Namespace(definitions)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsnamespacedefinitions "Direct link to heading") Creates a group of definitions (returns `DeclarationNamespace`) DefinitionsCreateResult[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionscreateresultt "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------- Contains the definition builders for a given definition (returned using [`Create`](https://rbxnet.australis.dev/docs/2.1/api/definitions#definitionscreatedefinitions) in Net.Definitions) interface DefinitionsCreateResult { readonly Server: ServerDefinitionBuilder; readonly Client: ClientDefinitionBuilder; } Copy ### Server[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#server "Direct link to heading") A [ServerDefinitionBuilder](https://rbxnet.australis.dev/docs/2.1/api/definitions#serverdefinitionbuildert) object. ### Client[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#client "Direct link to heading") A [ClientDefinitionBuilder](https://rbxnet.australis.dev/docs/2.1/api/definitions#clientdefinitionbuildert) object. ServerDefinitionBuilder[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#serverdefinitionbuildert "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------- Contains all the definition builders for server-side events and functions. class ServerDefinitionBuilder { Create(name: string): ServerEvent | ServerAsyncFunction | ServerFunction; GetNamespace(name: K): SeverDefinitionBuilder; OnEvent(name: string, callback: Callback): void; OnFunction(name: string, callback: Callback): void; } Copy ### Create(name)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#createname "Direct link to heading") Will get the specified event by name, and return it. The returned object will be the type provided in the definition. server/example.server.ts import { Server as ServerRemotes } from "shared/remotes.ts"; const TestRemote \= ServerRemotes.Create("TestRemote"); Copy ### OnFunction(name, callback)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#onfunctionname-callback "Direct link to heading") Similar to `Create` but only works on events, and is pretty much a shortcut for `Create(name).SetCallback(callback)` ### OnEvent(name, callback)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#oneventname-callback "Direct link to heading") Similar to `Create` but only works on events, and is pretty much a shortcut for `Create(name).Connect(callback)` ### GetNamespace(name)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#getnamespacename "Direct link to heading") Gets a child namespace under this namespace ClientDefinitionBuilder[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#clientdefinitionbuildert "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------- Contains all the definition builders for server-side events and functions. class ClientDefinitionBuilder { Get(name: string): ServerEvent | ServerAsyncFunction | ServerFunction; GetNamespace(name: K): ClientDefinitionBuilder; OnEvent(name: string, callback: Callback): void; } Copy ### Get(name)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#getname "Direct link to heading") Will get the specified event by name, and return it. The returned object will be the type provided in the definition. Gets the specified remote definition and gets the client version of the event/function/asyncfunction client/example.client.ts import { Client as ClientRemotes } from "shared/remotes.ts"; const TestRemote \= ClientRemotes.Get("TestRemote"); Copy ### OnEvent(name, callback)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#oneventname-callback-1 "Direct link to heading") Similar to `Get` but only works on events, and is pretty much a shortcut for `Create(name).Connect(callback)` ### GetNamespace(name)[#](https://rbxnet.australis.dev/docs/2.1/api/definitions/#getnamespacename-1 "Direct link to heading") Gets a child namespace under this namespace [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/api/net-definitions.md) * [Definitions.Create(definitions)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionscreatedefinitions) * [Definitions.ServerFunction(...)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsserverfunctionserver) * [Definitions.ServerToClientEvent(...)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsservertoclienteventserverargs) * [Definitions.ClientToServerEvent(...)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsclienttoservereventclientargs) * [Definitions.BidirectionalEvent(...)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsbidirectionaleventserverargs-clientargs) * [Definitions.ServerAsyncFunction(...)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsserverasyncfunctionserver) * [Definitions.Namespace(definitions)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionsnamespacedefinitions) * [DefinitionsCreateResult](https://rbxnet.australis.dev/docs/2.1/api/definitions/#definitionscreateresultt) * [Server](https://rbxnet.australis.dev/docs/2.1/api/definitions/#server) * [Client](https://rbxnet.australis.dev/docs/2.1/api/definitions/#client) * [ServerDefinitionBuilder](https://rbxnet.australis.dev/docs/2.1/api/definitions/#serverdefinitionbuildert) * [Create(name)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#createname) * [OnFunction(name, callback)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#onfunctionname-callback) * [OnEvent(name, callback)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#oneventname-callback) * [GetNamespace(name)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#getnamespacename) * [ClientDefinitionBuilder](https://rbxnet.australis.dev/docs/2.1/api/definitions/#clientdefinitionbuildert) * [Get(name)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#getname) * [OnEvent(name, callback)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#oneventname-callback-1) * [GetNamespace(name)](https://rbxnet.australis.dev/docs/2.1/api/definitions/#getnamespacename-1) --- # Net.Middleware Namespace | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/api/middleware) ** (3.0.10). Version: 2.1.5 TypeChecking[#](https://rbxnet.australis.dev/docs/2.1/api/middleware/#typechecking "Direct link to heading") ------------------------------------------------------------------------------------------------------------- ### Basic Type Checker[#](https://rbxnet.australis.dev/docs/2.1/api/middleware/#basic-type-checker "Direct link to heading") function TypeChecking(...checks: TypeCheck\[\]): TypeCheckingMiddleware Copy Function * Parameters * `...checks` Type checking functions in order of the arguments passed to the remote RateLimit[#](https://rbxnet.australis.dev/docs/2.1/api/middleware/#ratelimit "Direct link to heading") ------------------------------------------------------------------------------------------------------- The built-in rate limiting middleware. interface RateLimitError { Message: string; UserId: number; RemoteId: string; MaxRequestsPerMinute: number; } interface RateLimitOptions { MaxRequestsPerMinute: number; ErrorHandler?: (error: RateLimitError) \=> void; } function RateLimit(options: RateLimitOptions): RateLimitingMiddleware Copy Function * Parameters * `options` The options for the rate limiter Logging[#](https://rbxnet.australis.dev/docs/2.1/api/middleware/#logging "Direct link to heading") --------------------------------------------------------------------------------------------------- The built-in logging middleware interface LoggingOptions { Name?: string; Logger?: (name: string, args: unknown\[\]) \=> void; } function Logging(options?: LoggingOptions): LoggerMiddleware Copy Function * Parameters * `options` The options for the logger [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/api/net-middleware.md) * [TypeChecking](https://rbxnet.australis.dev/docs/2.1/api/middleware/#typechecking) * [Basic Type Checker](https://rbxnet.australis.dev/docs/2.1/api/middleware/#basic-type-checker) * [RateLimit](https://rbxnet.australis.dev/docs/2.1/api/middleware/#ratelimit) * [Logging](https://rbxnet.australis.dev/docs/2.1/api/middleware/#logging) --- # Install for Luau | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/install-luau) ** (3.0.10). Version: 2.0.0 Depending on your stack for Roblox, you might want to either use the [Rojo](https://rbxnet.australis.dev/docs/2.0/install-luau/#via-rojo) step or the [Studio](https://rbxnet.australis.dev/docs/2.0/install-luau/#via-studio) step. If you don't know what _Rojo_ is, use the Studio step. Via Rojo[#](https://rbxnet.australis.dev/docs/2.0/install-luau/#via-rojo "Direct link to heading") --------------------------------------------------------------------------------------------------- The following steps require knowledge and use of [rojo](https://rojo.space/) . If you're not using rojo, look at [studio](https://rbxnet.australis.dev/docs/2.0/install-luau/#via-studio) instructions. ##### danger Due to this being an older version, it is no longer available for Luau. Until Rotriever is released, there is no sane way of achieving this. :( Via Studio[#](https://rbxnet.australis.dev/docs/2.0/install-luau/#via-studio "Direct link to heading") ------------------------------------------------------------------------------------------------------- ### RBXMX model file[#](https://rbxnet.australis.dev/docs/2.0/install-luau/#rbxmx-model-file "Direct link to heading") Releases can be found [here](https://github.com/roblox-aurora/rbx-net/releases) . Download the appropriate `.rbxmx` file under the `Assets` dropdown, then drag it into studio. Ensure the library is under `ReplicatedStorage` so it can be used by all your code. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/install-lua.md) * [Via Rojo](https://rbxnet.australis.dev/docs/2.0/install-luau/#via-rojo) * [Via Studio](https://rbxnet.australis.dev/docs/2.0/install-luau/#via-studio) * [RBXMX model file](https://rbxnet.australis.dev/docs/2.0/install-luau/#rbxmx-model-file) --- # Runtime Type Checking | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/middleware/types) ** (3.0.10). Version: 2.0.0 It's important when you recieve events or calls from the server that you ensure the types are correct, otherwise unwanted errors may pop up. If you want to ensure the types you're recieving from the client _are_ the types you're expecting, you can use the [`Net.Middleware.TypeChecking`](https://rbxnet.australis.dev/docs/2.0/api/middleware#typechecking) middleware. This middleware just takes type checking functions. Using a library like `t`[#](https://rbxnet.australis.dev/docs/2.0/middleware/types/#using-a-library-like-t "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------- The rate limiter middleware is created as such: * roblox-ts * luau Net.Middleware.TypeCheck(t.string) Copy Net.Middleware.TypeCheck(t.string) Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/middleware/typecheck.md) * [Using a library like `t`](https://rbxnet.australis.dev/docs/2.0/middleware/types/#using-a-library-like-t) --- # API Overview | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/api) ** (3.0.10). Version: 2.0.0 [Net.Server](https://rbxnet.australis.dev/docs/2.0/api/server) [#](https://rbxnet.australis.dev/docs/2.0/api/#netserver "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------- Base namespace for the server [Net.Client](https://rbxnet.australis.dev/docs/2.0/api/client) [#](https://rbxnet.australis.dev/docs/2.0/api/#netclient "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------- Base namespace for the client [Net.Definitions](https://rbxnet.australis.dev/docs/2.0/api/definitions) [#](https://rbxnet.australis.dev/docs/2.0/api/#netdefinitions "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- The namespace for the [definitions](https://rbxnet.australis.dev/docs/2.0/definitions) feature. [Net.Middleware](https://rbxnet.australis.dev/docs/2.0/api/middleware) [#](https://rbxnet.australis.dev/docs/2.0/api/#netmiddleware "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------- The namespace for built in middleware [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/api/index.md) * [Net.Server](https://rbxnet.australis.dev/docs/2.0/api/#netserver) * [Net.Client](https://rbxnet.australis.dev/docs/2.0/api/#netclient) * [Net.Definitions](https://rbxnet.australis.dev/docs/2.0/api/#netdefinitions) * [Net.Middleware](https://rbxnet.australis.dev/docs/2.0/api/#netmiddleware) --- # Using Compile Time Remote IDs | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/uuid) ** (3.0.10). Version: 2.0.0 ##### TypeScript Only This functionality is only available to roblox-ts users. This is not possible in regular Luau. A feature that can be leveraged with the power of the roblox-ts compiler, is a thing referred to as "Remote Ids". This is a way to throw off any identifying information about your remotes to any external parties. If used correctly it should make it quite hard to make exploit tools for your game, and throw off most exploiters. ##### caution It is not an anti-exploit solution, but a [good piece of cheese](https://utkusen.com/blog/security-by-obscurity-is-underrated.html) in preventing exploits. You _should always_ secure your remotes yourself, using things like the [runtime type checking middleware](https://rbxnet.australis.dev/docs/2.0/middleware/types) . Doesn't hurt to add another layer of cheese. Getting started[#](https://rbxnet.australis.dev/docs/2.0/uuid/#getting-started "Direct link to heading") --------------------------------------------------------------------------------------------------------- To start using Remote Ids, first install the Remote Id generation tool: npm install -g roblox-ts-net-idgen Copy Then, create a new `remoteIds.id.json` file inside your project. It doesn't have to be called `remoteIds`, but for this example that's what we're doing. As long as it ends with `.id.json`. shared/remoteIds.id.json { "Name": "RemoteId", "IDs": \[\ \ \] } Copy The `Name` field is the outputted name of the `const enum`, and the `IDs` will be the IDs you have for your remotes. Now lets add some example remote ids shared/remoteIds.id.json { "Name": "RemoteId", "IDs": \[\ \ "PrintMessage",\ \ "MakeHello"\ \ \] } Copy Now that we have some remote ids, we need to generate the `type declaration` file. Run the command in your console: rbxnid Copy A new `remoteId.d.ts` file should have been generated, and should look like the following: shared/remoteId.d.ts export const enum RemoteId { PrintMessage \= "cbf11f23-ed6e-43f6-8750-fce7c6558ae4", MakeHello \= "ffa61bfe-d8ba-4c82-a7eb-3dd36b133184" } Copy These IDs will change every time you run the `rbxnid` command. It's recommended you do this as part of your build process, so each new build of your game has an entirely new set of IDs. This will ensure that it's difficult to make any specific exploit tools for your game. Usage[#](https://rbxnet.australis.dev/docs/2.0/uuid/#usage "Direct link to heading") ------------------------------------------------------------------------------------- Then when you have the RemoteIds, you can use them in place where you'd normally supply a remote id: import Net from "@rbxts/net"; import { RemoteId } from "shared/remoteId"; const ExampleUsage \= new Net.Server.Event(RemoteId.PrintMessage); Copy This will end up compiling to compiled code \--- ... roblox-ts imports local ExampleUsage = Net.Server.Event.new("cbf11f23-ed6e-43f6-8750-fce7c6558ae4") Copy ### Using with Definitions[#](https://rbxnet.australis.dev/docs/2.0/uuid/#using-with-definitions "Direct link to heading") Using remote ids with definitions is straightforward. import Net from "@rbxts/net"; import { RemoteId } from "shared/remoteId"; const Remotes \= Net.Definitions.Create({ \[RemoteId.PrintMessage\]: Net.Definitions.Event<\[message: string\]\>(), \[RemoteId.MakeHello\]: Net.Definitions.AsyncFunction<(message: string) \=> string\>() }); export \= Remotes; Copy Which should compile to the following: compiled code \-- ... roblox-ts imports local Remotes = Net.Definitions.Create({ \["cbf11f23-ed6e-43f6-8750-fce7c6558ae4"\] = Net.Definitions.Event(), \["ffa61bfe-d8ba-4c82-a7eb-3dd36b133184"\] = Net.Definitions.AsyncFunction() }) \-- .. exports Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/guides/uuid.md) * [Getting started](https://rbxnet.australis.dev/docs/2.0/uuid/#getting-started) * [Usage](https://rbxnet.australis.dev/docs/2.0/uuid/#usage) * [Using with Definitions](https://rbxnet.australis.dev/docs/2.0/uuid/#using-with-definitions) --- # Writing custom middleware | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/middleware/custom) ** (3.0.10). Version: 2.0.0 [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/middleware/custom.md) --- # Rate limiting your remotes | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/middleware/rate-limit) ** (3.0.10). Version: 2.0.0 Your event or AsyncFunction may perform an intensive task that you don't want players to be able to invoke every second (and possibly crash your game) A way you can get around this is by using the [`Net.Middleware.RateLimit`](https://rbxnet.australis.dev/docs/2.0/api/middleware#ratelimit) middleware. This is a built in. Limiting to a certain amount of requests[#](https://rbxnet.australis.dev/docs/2.0/middleware/rate-limit/#limiting-to-a-certain-amount-of-requests "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The rate limiter middleware is created as such: * roblox-ts * luau Net.Middleware.RateLimit({ MaxRequestsPerMinute: 1 // This can be the amount of requests you want to limit per minute }) Copy Net.Middleware.RateLimit({ MaxRequestsPerMinute = 1 -- This can be the amount of requests you want to limit per minute }) Copy Then you pass it to a constructor for a server object, or a definition: * roblox-ts * luau Object const Example \= new Net.Server.AsyncFunction("Example", \[\ \ Net.Middleware.RateLimit({\ \ MaxRequestsPerMinute: 1\ \ })\ \ \]) Copy Definition const Remotes \= Net.Definitions.Create({ Example: Net.Definitions.AsyncFunction(\[\ \ Net.Middleware.RateLimit({\ \ MaxRequestsPerMinute: 1\ \ })\ \ \]) }) Copy Object local Example = Net.Server.AsyncFunction.new("Example", { Net.Middleware.RateLimit({ MaxRequestsPerMinute = 1 }) }) Copy Definition local Remotes = Net.Definitions.Create({ Example = Net.Definitions.AsyncFunction({ Net.Middleware.RateLimit({ MaxRequestsPerMinute: 1 }) }) }) Copy Custom Error Handling[#](https://rbxnet.australis.dev/docs/2.0/middleware/rate-limit/#custom-error-handling "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------- When the rate limit is reached, it will run the error handler. By default this is set to a function which displays a warning on the server: export function rateLimitWarningHandler(error: RateLimitError) { warn("\[rbx-net\]", error.Message); } Copy However, if you want to send this to something like analytics, you can provide your own error handler: * roblox-ts * luau function analyticRateLimitError(error: RateLimitError) { AnalyticsService.Error(error.Message); // this is just an example } Copy Object const Example \= new Net.Server.AsyncFunction("Example", \[\ \ Net.Middleware.RateLimit({\ \ MaxRequestsPerMinute: 1,\ \ ErrorHandler: analyticRateLimitError\ \ })\ \ \]) Copy Definition const Remotes \= Net.Definitions.Create({ Example: Net.Definitions.AsyncFunction(\[\ \ Net.Middleware.RateLimit({\ \ MaxRequestsPerMinute: 1,\ \ ErrorHandler: analyticRateLimitError\ \ })\ \ \]) }) Copy local function analyticRateLimitError(error) AnalyticsService:Error(error.Message) -- this is just an example end Copy Object local Example = Net.Server.AsyncFunction.new("Example", { Net.Middleware.RateLimit({ MaxRequestsPerMinute = 1, ErrorHandler = analyticRateLimitError }) }) Copy Definition local Remotes = Net.Definitions.Create({ Example = Net.Definitions.AsyncFunction({ Net.Middleware.RateLimit({ MaxRequestsPerMinute: 1, ErrorHandler = analyticRateLimitError }) }) }) Copy [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/middleware/ratelimit.md) * [Limiting to a certain amount of requests](https://rbxnet.australis.dev/docs/2.0/middleware/rate-limit/#limiting-to-a-certain-amount-of-requests) * [Custom Error Handling](https://rbxnet.australis.dev/docs/2.0/middleware/rate-limit/#custom-error-handling) --- # Basics | RbxNet This is documentation for RbxNet **2.1.5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/basic-usage) ** (3.0.10). Version: 2.1.5 Quick Start[#](https://rbxnet.australis.dev/docs/2.1/basic-usage#quick-start "Direct link to heading") ------------------------------------------------------------------------------------------------------- Three files are needed to get started: * roblox-ts * luau shared/remotes.ts import Net from "@rbxts/net"; const Remotes \= Net.Definitions.Create({ PrintMessage: Net.Definitions.ClientToServerEvent<\[message: string, other: string\]\>(), MakeHello: Net.Definitions.ServerAsyncFunction<(message: string) \=> string\>(), }); export { Remotes }; Copy server/test.server.ts import { Remotes } from "shared/remotes"; // listen to messages const PrintMessage \= Remotes.Server.Create("PrintMessage"); PrintMessage.Connect((player, message, other) \=> { print(\`Server recieved message: ${message} from player: ${player} ${other}\`); }); // listen and respond to messages const MakeHello \= Remotes.Server.Create("MakeHello"); MakeHello.SetCallback((player, message) \=> { print(\`Server got an async message from ${player} containing the message ${message}\`); return \`Hello, ${player}! We got your message: ${message}\`; }); Copy client/test.client.ts import { Remotes } from "shared/remotes"; // send a message to the server const PrintMessage \= Remotes.Client.Get("PrintMessage"); PrintMessage.SendToServer("Hello there!", "other"); // send a message to the server, while listening for a response const MakeHello \= Remotes.Client.Get("MakeHello"); MakeHello.CallServerAsync("Net is cool right??").then((result) \=> { print(\`Client got a response to the async message from server: ${result}\`); }); Copy src/shared/Remotes.lua local Net \= require(ReplicatedStorage.Net) local Remotes \= Net.Definitions.Create({ PrintMessage \= Net.Definitions.ClientToServerEvent(), MakeHello \= Net.Definitions.ServerAsyncFunction(), }) return Remotes Copy src/server/test.server.lua local Remotes \= require(ReplicatedStorage.Common.Remotes) \-- listen to messages local PrintMessage \= Remotes.Server:Create("PrintMessage") PrintMessage:Connect(function (player, message, other) print("Server recieved message", message, "from player:", player, other) end) \-- listen and respond to messages local MakeHello \= Remotes.Server:Create("MakeHello") MakeHello:SetCallback(function (player, message) print("Server got an async message from ", player, "containing the message", message) return "Hello, " .. tostring(player) .. " We got your message: " .. message end) Copy src/client/test.client.lua local Remotes \= require(ReplicatedStorage.Common.Remotes) \-- send a message to the server local PrintMessage \= Remotes.Client:Get("PrintMessage"); PrintMessage:SendToServer("Hello there!", "other"); \-- send a message to the server, while listening for a response local MakeHello \= Remotes.Client:Get("MakeHello"); MakeHello:CallServerAsync("Net is cool right??"):andThen(function (result) print("Client got a response to the async message from server: ", result) end) Copy And away you go - just get editing the remotes file to add your own definitions! [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.1.x/guides/basic-usage.md) * [Quick Start](https://rbxnet.australis.dev/docs/2.1/basic-usage#quick-start) --- # Net.Server Namespace | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/api/server) ** (3.0.10). Version: 2.0.0 This contains all the server-related code relating to Net Event[#](https://rbxnet.australis.dev/docs/2.0/api/server/#event "Direct link to heading") ------------------------------------------------------------------------------------------- class ServerEvent { constructor(name: string, middleware?: Middleware); GetInstance(): RemoteEvent; Connect(callback: (player: Player, ...args: ConnectArgs) \=> void): RBXScriptConnection; SendToAllPlayers(...args: CallArgs): void; SendToAllPlayersExcept(blacklist: Player | Player\[\], ...args: CallArgs): void; SendToPlayer(player: Player, ...args: CallArgs): void; SendToPlayers(players: Player\[\], ...args: CallArgs): void; } Copy ### GetInstance[#](https://rbxnet.australis.dev/docs/2.0/api/server/#getinstance "Direct link to heading") ### Connect[#](https://rbxnet.australis.dev/docs/2.0/api/server/#connect "Direct link to heading") ### SendToAllPlayers[#](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoallplayers "Direct link to heading") ### SendToAllPlayersExcept[#](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoallplayersexcept "Direct link to heading") ### SendToPlayer[#](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoplayer "Direct link to heading") ### SendToPlayers[#](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoplayers "Direct link to heading") Function[#](https://rbxnet.australis.dev/docs/2.0/api/server/#function "Direct link to heading") ------------------------------------------------------------------------------------------------- class ServerFunction { constructor(name: string, middleware?: Middleware); GetInstance(): RemoteFunction; SetCallback(callback: (player: Player, ...args: CallbackArgs) \=> Returns): void; } Copy ### GetInstance[#](https://rbxnet.australis.dev/docs/2.0/api/server/#getinstance-1 "Direct link to heading") ### SetCallback[#](https://rbxnet.australis.dev/docs/2.0/api/server/#setcallback "Direct link to heading") AsyncFunction[#](https://rbxnet.australis.dev/docs/2.0/api/server/#asyncfunction "Direct link to heading") ----------------------------------------------------------------------------------------------------------- class ServerAsyncFunction { constructor(name: string, middleware?: Middleware); GetInstance(): RemoteEvent; SetCallback(callback: (player: Player, ...args: CallbackArgs) \=> any): void; CallPlayerAsync(player: Player, ...args: CallArgs): Promise; } Copy ### GetInstance[#](https://rbxnet.australis.dev/docs/2.0/api/server/#getinstance-2 "Direct link to heading") ### SetCallback[#](https://rbxnet.australis.dev/docs/2.0/api/server/#setcallback-1 "Direct link to heading") ### CallPlayerAsync[#](https://rbxnet.australis.dev/docs/2.0/api/server/#callplayerasync "Direct link to heading") CrossServerEvent[#](https://rbxnet.australis.dev/docs/2.0/api/server/#crossserverevent "Direct link to heading") ----------------------------------------------------------------------------------------------------------------- class CrossServerEvent { constructor(name: string); SendToAllServers(...args: unknown\[\]): void; SendToServer(jobId: string, ...args: unknown\[\]): void; SendToPlayer(userId: number, ...args: unknown\[\]): void; SendToPlayers(userIds: number\[\], ...args: unknown\[\]): void; Disconnect(): void; } Copy ### SendToAllServers[#](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoallservers "Direct link to heading") ### SendToServer[#](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoserver "Direct link to heading") ### SendToPlayer[#](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoplayer-1 "Direct link to heading") ### SendToPlayers[#](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoplayers-1 "Direct link to heading") ### Disconnect[#](https://rbxnet.australis.dev/docs/2.0/api/server/#disconnect "Direct link to heading") [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/api/net-server.md) * [Event](https://rbxnet.australis.dev/docs/2.0/api/server/#event) * [GetInstance](https://rbxnet.australis.dev/docs/2.0/api/server/#getinstance) * [Connect](https://rbxnet.australis.dev/docs/2.0/api/server/#connect) * [SendToAllPlayers](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoallplayers) * [SendToAllPlayersExcept](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoallplayersexcept) * [SendToPlayer](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoplayer) * [SendToPlayers](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoplayers) * [Function](https://rbxnet.australis.dev/docs/2.0/api/server/#function) * [GetInstance](https://rbxnet.australis.dev/docs/2.0/api/server/#getinstance-1) * [SetCallback](https://rbxnet.australis.dev/docs/2.0/api/server/#setcallback) * [AsyncFunction](https://rbxnet.australis.dev/docs/2.0/api/server/#asyncfunction) * [GetInstance](https://rbxnet.australis.dev/docs/2.0/api/server/#getinstance-2) * [SetCallback](https://rbxnet.australis.dev/docs/2.0/api/server/#setcallback-1) * [CallPlayerAsync](https://rbxnet.australis.dev/docs/2.0/api/server/#callplayerasync) * [CrossServerEvent](https://rbxnet.australis.dev/docs/2.0/api/server/#crossserverevent) * [SendToAllServers](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoallservers) * [SendToServer](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoserver) * [SendToPlayer](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoplayer-1) * [SendToPlayers](https://rbxnet.australis.dev/docs/2.0/api/server/#sendtoplayers-1) * [Disconnect](https://rbxnet.australis.dev/docs/2.0/api/server/#disconnect) --- # Basics | RbxNet Version: 3.0.10 Quick Start[#](https://rbxnet.australis.dev/docs/3.0/basic-usage#quick-start "Direct link to heading") ------------------------------------------------------------------------------------------------------- Three files are needed to get started: * roblox-ts * luau shared/remotes.ts import Net from "@rbxts/net"; const Remotes \= Net.CreateDefinitions({ PrintMessage: Net.Definitions.ClientToServerEvent<\[message: string, other: string\]\>(), MakeHello: Net.Definitions.ServerAsyncFunction<(message: string) \=> string\>(), }); export { Remotes }; Copy server/test.server.ts import { Remotes } from "shared/remotes"; // listen to messages const PrintMessage \= Remotes.Server.Get("PrintMessage"); PrintMessage.Connect((player, message, other) \=> { print(\`Server recieved message: ${message} from player: ${player} ${other}\`); }); // listen and respond to messages const MakeHello \= Remotes.Server.Get("MakeHello"); MakeHello.SetCallback((player, message) \=> { print(\`Server got an async message from ${player} containing the message ${message}\`); return \`Hello, ${player}! We got your message: ${message}\`; }); Copy client/test.client.ts import { Remotes } from "shared/remotes"; // send a message to the server const PrintMessage \= Remotes.Client.Get("PrintMessage"); PrintMessage.SendToServer("Hello there!", "other"); // send a message to the server, while listening for a response const MakeHello \= Remotes.Client.Get("MakeHello"); MakeHello.CallServerAsync("Net is cool right??").then((result) \=> { print(\`Client got a response to the async message from server: ${result}\`); }); Copy src/shared/Remotes.lua local Net \= require(ReplicatedStorage.Net) local Remotes \= Net.CreateDefinitions({ PrintMessage \= Net.Definitions.ClientToServerEvent(), MakeHello \= Net.Definitions.ServerAsyncFunction(), }) return Remotes Copy src/server/test.server.lua local Remotes \= require(ReplicatedStorage.Common.Remotes) \-- listen to messages local PrintMessage \= Remotes.Server:Get("PrintMessage") PrintMessage:Connect(function (player, message, other) print("Server recieved message", message, "from player:", player, other) end) \-- listen and respond to messages local MakeHello \= Remotes.Server:Get("MakeHello") MakeHello:SetCallback(function (player, message) print("Server got an async message from ", player, "containing the message", message) return "Hello, " .. tostring(player) .. " We got your message: " .. message end) Copy src/client/test.client.lua local Remotes \= require(ReplicatedStorage.Common.Remotes) \-- send a message to the server local PrintMessage \= Remotes.Client:Get("PrintMessage"); PrintMessage:SendToServer("Hello there!", "other"); \-- send a message to the server, while listening for a response local MakeHello \= Remotes.Client:Get("MakeHello"); MakeHello:CallServerAsync("Net is cool right??"):andThen(function (result) print("Client got a response to the async message from server: ", result) end) Copy And away you go - just get editing the remotes file to add your own definitions! [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/docs/guides/basic-usage.md) * [Quick Start](https://rbxnet.australis.dev/docs/3.0/basic-usage#quick-start) --- # Net.Middleware Namespace | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/api/middleware) ** (3.0.10). Version: 2.0.0 TypeChecking[#](https://rbxnet.australis.dev/docs/2.0/api/middleware/#typechecking "Direct link to heading") ------------------------------------------------------------------------------------------------------------- ### Basic Type Checker[#](https://rbxnet.australis.dev/docs/2.0/api/middleware/#basic-type-checker "Direct link to heading") function TypeChecking(...checks: TypeCheck\[\]): TypeCheckingMiddleware Copy Function * Parameters * `...checks` Type checking functions in order of the arguments passed to the remote RateLimit[#](https://rbxnet.australis.dev/docs/2.0/api/middleware/#ratelimit "Direct link to heading") ------------------------------------------------------------------------------------------------------- The built-in rate limiting middleware. interface RateLimitError { Message: string; UserId: number; RemoteId: string; MaxRequestsPerMinute: number; } interface RateLimitOptions { MaxRequestsPerMinute: number; ErrorHandler?: (error: RateLimitError) \=> void; } function RateLimit(options: RateLimitOptions): RateLimitingMiddleware Copy Function * Parameters * `options` The options for the rate limiter Logging[#](https://rbxnet.australis.dev/docs/2.0/api/middleware/#logging "Direct link to heading") --------------------------------------------------------------------------------------------------- The built-in logging middleware interface LoggingOptions { Name?: string; Logger?: (name: string, args: unknown\[\]) \=> void; } function Logging(options?: LoggingOptions): LoggerMiddleware Copy Function * Parameters * `options` The options for the logger [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/api/net-middleware.md) * [TypeChecking](https://rbxnet.australis.dev/docs/2.0/api/middleware/#typechecking) * [Basic Type Checker](https://rbxnet.australis.dev/docs/2.0/api/middleware/#basic-type-checker) * [RateLimit](https://rbxnet.australis.dev/docs/2.0/api/middleware/#ratelimit) * [Logging](https://rbxnet.australis.dev/docs/2.0/api/middleware/#logging) --- # Wrapping Custom Player Objects | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/custom-player-objects) ** (3.0.10). Version: 2.0.0 How one might do it[#](https://rbxnet.australis.dev/docs/2.0/custom-player-objects/#how-one-might-do-it "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------- A common pattern when using remotes - on the server - is to require casting a player to an object representation of the player. This may come as the following sort of situation: * roblox-ts * luau import PlayerService from "server/Services/PlayerService"; const PlayerEquipItem \= new Net.Server.Event<\[itemId: number\]\>("PlayerEquipItem") PlayerEquipItem.Connect((player, itemId) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { entity.EquipItem(itemId); } }) const PlayerUnequipItem \= new Net.Server.Event<\[itemId: number\]\>("PlayerUnequipItem") PlayerUnequipItem.Connect((player, itemId) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { entity.UnequipItem(itemId); } }) const GetPlayerEquipped \= new Net.Server.AsyncFunction("GetPlayerEquipped") GetPlayerEquipped.SetCallback((player) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { return entity.GetEquippedItems(); } }) Copy local PlayerService = require(ServerScriptService.Services.PlayerService) local PlayerEquipItem = Net.Server.Event.new("PlayerEquipItem") PlayerEquipItem:Connect(function (player, itemId) local entity = PlayerService:GetEntity(player) if entity then entity:EquipItem(itemId) end end) local PlayerUnequipItem = Net.Server.Event.new("PlayerUnequipItem") PlayerUnequipItem:Connect(function (player, itemId) local entity = PlayerService:GetEntity(player) if entity then entity:UnequipItem(itemId) end end) local GetPlayerEquipped = Net.Server.AsyncFunction.new("GetPlayerEquipped") GetPlayerEquipped:SetCallback(function(player) local entity = PlayerService:GetEntity(player) if entity then return entity:GetEquippedItems() end end) Copy As you might have noticed, there's some repeated code where we're repetitively having to grab the player entity here in place of the player. We can instead use what's called a _wrapper_ to do this for us and make it as if we were connecting directly to the remote and it had the entity as the player argument rather than a player. Using a wrapper[#](https://rbxnet.australis.dev/docs/2.0/custom-player-objects/#using-a-wrapper "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------- We can define a `withPlayerEntity` wrapper, which will achieve what we're doing above in each remote separately. This is the recommended method when augmenting the player argument as it's the safest method and guaranteed to run after all the middleware. * roblox-ts * luau server/Wrappers/withPlayerEntity.ts import PlayerService from "server/Services/PlayerService"; import PlayerEntity from "server/Classes/PlayerEntity"; export default function withPlayerEntity, R \= void\>( fn: (playerEntity: PlayerEntity, ...args: T) \=> R, ) { return (player: Player, ...args: T) \=> { const entity \= PlayerService.GetEntity(player); if (entity) { return fn(entity, ...args); } }; } Copy src/server/Wrappers/withPlayerEntity.lua local PlayerService = require(ServerScriptService.Services.PlayerService) local function withPlayerEntity(fn) return function (player, ...) local entity = playerService:GetEntity(player) if entity then return fn(entity, ...) end end end return withPlayerEntity Copy Then we can apply this to the code above. * roblox-ts * luau import PlayerService from "server/Services/PlayerService"; import withPlayerEntity from "server/Wrappers/withPlayerEntity"; const PlayerEquipItem \= new Net.Server.Event<\[itemId: number\]\>("PlayerEquipItem") PlayerEquipItem.Connect( withPlayerEntity((entity, itemId) \=> { entity.EquipItem(itemId); }) ); const PlayerUnequipItem \= new Net.Server.Event<\[itemId: number\]\>("PlayerUnequipItem") PlayerUnequipItem.Connect((player, itemId) \=> { withPlayerEntity((entity, itemId) \=> { entity.UnequipItem(itemId); }) }) const GetPlayerEquipped \= new Net.Server.AsyncFunction("GetPlayerEquipped") GetPlayerEquipped.SetCallback( withPlayerEntity((player) \=> { return entity.GetEquippedItems(); }) ) Copy local PlayerService = require(ServerScriptService.Services.PlayerService) local withPlayerEntity = require(ServerScriptService.Wrappers.withPlayerEntity) local PlayerEquipItem = Net.Server.Event.new("PlayerEquipItem") PlayerEquipItem:Connect( withPlayerEntity(function (entity, itemId) entity:EquipItem(itemId) end) ) local PlayerUnequipItem = Net.Server.Event.new("PlayerUnequipItem") PlayerUnequipItem:Connect( withPlayerEntity(function (player, itemId) entity:UnequipItem(itemId) end) ) local GetPlayerEquipped = Net.Server.AsyncFunction.new("GetPlayerEquipped") GetPlayerEquipped:SetCallback( withPlayerEntity(function(player) return entity:GetEquippedItems() end) ) Copy And as you can see, this reduces repetitive code and gives us the `PlayerEntity` object to work with. Simple as that. [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/guides/connect-wrapper.md) * [How one might do it](https://rbxnet.australis.dev/docs/2.0/custom-player-objects/#how-one-might-do-it) * [Using a wrapper](https://rbxnet.australis.dev/docs/2.0/custom-player-objects/#using-a-wrapper) --- # Net.Client Namespace | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/api/client) ** (3.0.10). Version: 2.0.0 This contains all the client-related code relating to Net Event[#](https://rbxnet.australis.dev/docs/2.0/api/client/#event "Direct link to heading") ------------------------------------------------------------------------------------------- class ClientEvent { constructor(name: string); SendToServer(...args: CallArguments): void; Connect(callback: (...args: ConnectArgs) \=> void): RBXScriptConnection; } Copy ### SendToServer[#](https://rbxnet.australis.dev/docs/2.0/api/client/#sendtoserver "Direct link to heading") ### Connect[#](https://rbxnet.australis.dev/docs/2.0/api/client/#connect "Direct link to heading") Function[#](https://rbxnet.australis.dev/docs/2.0/api/client/#function "Direct link to heading") ------------------------------------------------------------------------------------------------- class ClientFunction { constructor(name: string); CallServerAsync(...args: CallArgs): Promise; } Copy ### CallServerAsync[#](https://rbxnet.australis.dev/docs/2.0/api/client/#callserverasync "Direct link to heading") AsyncFunction[#](https://rbxnet.australis.dev/docs/2.0/api/client/#asyncfunction "Direct link to heading") ----------------------------------------------------------------------------------------------------------- class ClientAsyncFunction { constructor(name: string); CallServerAsync(...args: CallArgs): Promise; SetCallback(callback: (...args: CallbackArgs) \=> any): void; SetCallTimeout(timeout: number): void; GetCallTimeout(): number; } Copy ### CallServerAsync[#](https://rbxnet.australis.dev/docs/2.0/api/client/#callserverasync-1 "Direct link to heading") ### SetCallback[#](https://rbxnet.australis.dev/docs/2.0/api/client/#setcallback "Direct link to heading") ### SetCallTimeout[#](https://rbxnet.australis.dev/docs/2.0/api/client/#setcalltimeout "Direct link to heading") ### GetCalllTimeout[#](https://rbxnet.australis.dev/docs/2.0/api/client/#getcallltimeout "Direct link to heading") CrossServerEvent[#](https://rbxnet.australis.dev/docs/2.0/api/client/#crossserverevent "Direct link to heading") ----------------------------------------------------------------------------------------------------------------- class CrossServerEvent { constructor(name: string); Connect(callback: (...args: unknown\[\]) \=> void): void; } Copy ### Connect[#](https://rbxnet.australis.dev/docs/2.0/api/client/#connect-1 "Direct link to heading") [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/api/net-client.md) * [Event](https://rbxnet.australis.dev/docs/2.0/api/client/#event) * [SendToServer](https://rbxnet.australis.dev/docs/2.0/api/client/#sendtoserver) * [Connect](https://rbxnet.australis.dev/docs/2.0/api/client/#connect) * [Function](https://rbxnet.australis.dev/docs/2.0/api/client/#function) * [CallServerAsync](https://rbxnet.australis.dev/docs/2.0/api/client/#callserverasync) * [AsyncFunction](https://rbxnet.australis.dev/docs/2.0/api/client/#asyncfunction) * [CallServerAsync](https://rbxnet.australis.dev/docs/2.0/api/client/#callserverasync-1) * [SetCallback](https://rbxnet.australis.dev/docs/2.0/api/client/#setcallback) * [SetCallTimeout](https://rbxnet.australis.dev/docs/2.0/api/client/#setcalltimeout) * [GetCalllTimeout](https://rbxnet.australis.dev/docs/2.0/api/client/#getcallltimeout) * [CrossServerEvent](https://rbxnet.australis.dev/docs/2.0/api/client/#crossserverevent) * [Connect](https://rbxnet.australis.dev/docs/2.0/api/client/#connect-1) --- # Logging | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/middleware/logging) ** (3.0.10). Version: 2.0.0 [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/middleware/logger.md) --- # Net.Definitions Namespace | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/api/definitions) ** (3.0.10). Version: 2.0.0 This namespace is for the Definitions feature. ### Create(definitions)[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#createdefinitions "Direct link to heading") function Create(remotes: T): DefinitionBuilders Copy Function * Parameters * `remotes` An object of remote definitions. See [definitions](https://rbxnet.australis.dev/docs/2.0/definitions#definitions-oh-my) for usage. * Returns a [DefinitionBuilders](https://rbxnet.australis.dev/docs/2.0/api/definitions/#definitionbuilderst) Example shared/remotes.ts import Net from "@rbxts/net"; const MyDefinitions \= Net.Definitions.Create({ TestRemote: Net.Definitions.AsyncFunction<(name: string) \=> boolean\>() }); Copy ### Function(...)[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#functionserver "Direct link to heading") Definition function for creating a `FunctionDefinition` ### Event(...)[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#eventserverargs-clientargs "Direct link to heading") Definition function for creating an `EventDefinition` ### AsyncFunction(...)[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#asyncfunctionserver-client "Direct link to heading") Definition function for creating an `AsyncDefinition` Net.Middleware[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#netmiddleware "Direct link to heading") ----------------------------------------------------------------------------------------------------------------- This namespace contains built-in middleware for RbxNet. ### RateLimit(limit)[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#ratelimitlimit "Direct link to heading") ### RuntimeTypeCheck(...typeCheckers)[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#runtimetypechecktypecheckers "Direct link to heading") DefinitionsCreateResult[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#definitionscreateresultt "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------- Contains the definition builders for a given definition (returned using [`Create`](https://rbxnet.australis.dev/docs/2.0/api/definitions#createdefinitions) in Net.Definitions) interface DefinitionsCreateResult { readonly Server: ServerDefinitionBuilder; readonly Client: ClientDefinitionBuilder; } Copy ### Server[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#server "Direct link to heading") A [ServerDefinitionBuilder](https://rbxnet.australis.dev/docs/2.0/api/definitions#serverdefinitionbuildert) object. ### Client[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#client "Direct link to heading") A [ClientDefinitionBuilder](https://rbxnet.australis.dev/docs/2.0/api/definitions#clientdefinitionbuildert) object. ServerDefinitionBuilder[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#serverdefinitionbuildert "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------- Contains all the definition builders for server-side events and functions. class ServerDefinitionBuilder { Create(name: string): ServerEvent | ServerAsyncFunction | ServerFunction; ConnectEvent(name: string, callback: Callback): void; } Copy ### Create(name)[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#createname "Direct link to heading") Will get the specified event by name, and return it. The returned object will be the type provided in the definition. server/example.server.ts import { Server as ServerRemotes } from "shared/remotes.ts"; const TestRemote \= ServerRemotes.Create("TestRemote"); Copy ### ConnectEvent(name, callback)[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#connecteventname-callback "Direct link to heading") Similar to `Create` but only works on events, and is pretty much a shortcut for `Create(name).Connect(callback)` ClientDefinitionBuilder[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#clientdefinitionbuildert "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------- Contains all the definition builders for server-side events and functions. class ClientDefinitionBuilder { Get(name: string): ServerEvent | ServerAsyncFunction | ServerFunction; ConnectEvent(name: string, callback: Callback): void; } Copy ### Get(name)[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#getname "Direct link to heading") Will get the specified event by name, and return it. The returned object will be the type provided in the definition. Gets the specified remote definition and gets the client version of the event/function/asyncfunction client/example.client.ts import { Client as ClientRemotes } from "shared/remotes.ts"; const TestRemote \= ClientRemotes.Get("TestRemote"); Copy ### ConnectEvent(name, callback)[#](https://rbxnet.australis.dev/docs/2.0/api/definitions/#connecteventname-callback-1 "Direct link to heading") Similar to `Get` but only works on events, and is pretty much a shortcut for `Create(name).Connect(callback)` [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/api/net-definitions.md) * [Create(definitions)](https://rbxnet.australis.dev/docs/2.0/api/definitions/#createdefinitions) * [Function(...)](https://rbxnet.australis.dev/docs/2.0/api/definitions/#functionserver) * [Event(...)](https://rbxnet.australis.dev/docs/2.0/api/definitions/#eventserverargs-clientargs) * [AsyncFunction(...)](https://rbxnet.australis.dev/docs/2.0/api/definitions/#asyncfunctionserver-client) * [Net.Middleware](https://rbxnet.australis.dev/docs/2.0/api/definitions/#netmiddleware) * [RateLimit(limit)](https://rbxnet.australis.dev/docs/2.0/api/definitions/#ratelimitlimit) * [RuntimeTypeCheck(...typeCheckers)](https://rbxnet.australis.dev/docs/2.0/api/definitions/#runtimetypechecktypecheckers) * [DefinitionsCreateResult](https://rbxnet.australis.dev/docs/2.0/api/definitions/#definitionscreateresultt) * [Server](https://rbxnet.australis.dev/docs/2.0/api/definitions/#server) * [Client](https://rbxnet.australis.dev/docs/2.0/api/definitions/#client) * [ServerDefinitionBuilder](https://rbxnet.australis.dev/docs/2.0/api/definitions/#serverdefinitionbuildert) * [Create(name)](https://rbxnet.australis.dev/docs/2.0/api/definitions/#createname) * [ConnectEvent(name, callback)](https://rbxnet.australis.dev/docs/2.0/api/definitions/#connecteventname-callback) * [ClientDefinitionBuilder](https://rbxnet.australis.dev/docs/2.0/api/definitions/#clientdefinitionbuildert) * [Get(name)](https://rbxnet.australis.dev/docs/2.0/api/definitions/#getname) * [ConnectEvent(name, callback)](https://rbxnet.australis.dev/docs/2.0/api/definitions/#connecteventname-callback-1) --- # Basics | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/basic-usage) ** (3.0.10). Version: 2.0.0 Quick Start[#](https://rbxnet.australis.dev/docs/2.0/basic-usage/#quick-start "Direct link to heading") -------------------------------------------------------------------------------------------------------- Three files are needed to get started: * roblox-ts * luau shared/remotes.ts import Net from "@rbxts/net"; const Remotes \= Net.Definitions.Create({ PrintMessage: Net.Definitions.Event<\[message: string, other: string\]\>(), MakeHello: Net.Definitions.AsyncFunction<(message: string) \=> string\>(), }); export { Remotes }; Copy server/test.server.ts import { Remotes } from "shared/remotes"; // listen to messages const PrintMessage \= Remotes.Server.Create("PrintMessage"); PrintMessage.Connect((player, message, other) \=> { print(\`Server recieved message: ${message} from player: ${player} ${other}\`); }); // listen and respond to messages const MakeHello \= Remotes.Server.Create("MakeHello"); MakeHello.SetCallback((player, message) \=> { print(\`Server got an async message from ${player} containing the message ${message}\`); return \`Hello, ${player}! We got your message: ${message}\`; }); Copy client/test.client.ts import { Remotes } from "shared/remotes"; // send a message to the server const PrintMessage \= Remotes.Client.Get("PrintMessage"); PrintMessage.SendToServer("Hello there!", "other"); // send a message to the server, while listening for a response const MakeHello \= Remotes.Client.Get("MakeHello"); MakeHello.CallServerAsync("Net is cool right??").then((result) \=> { print(\`Client got a response to the async message from server: ${result}\`); }); Copy src/shared/Remotes.lua local Net = require(ReplicatedStorage.Net) local Remotes = Net.Definitions.Create({ PrintMessage = Net.Definitions.Event(), MakeHello = Net.Definitions.AsyncFunction(), }) return Remotes Copy src/server/test.server.lua local Remotes = require(ReplicatedStorage.Common.Remotes) \-- listen to messages local PrintMessage = Remotes:CreateServer("PrintMessage") PrintMessage:Connect(function (player, message, other) print("Server recieved message", message, "from player:", player, other) end) \-- listen and respond to messages local MakeHello = Remotes:CreateServer("MakeHello") MakeHello:SetCallback(function (player, message) print("Server got an async message from ", player, "containing the message", message) return "Hello, " .. tostring(player) .. " We got your message: " .. message end) Copy src/client/test.client.lua local Remotes = require(ReplicatedStorage.Common.Remotes) \-- send a message to the server local PrintMessage = Remotes:GetClient("PrintMessage"); PrintMessage:SendToServer("Hello there!", "other"); \-- send a message to the server, while listening for a response local MakeHello = Remotes:GetClient("MakeHello"); MakeHello:CallServerAsync("Net is cool right??"):andThen(function (result) print("Client got a response to the async message from server: ", result) end) Copy And away you go - just get editing the remotes file to add your own definitions! [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/guides/basic-usage.md) * [Quick Start](https://rbxnet.australis.dev/docs/2.0/basic-usage/#quick-start) --- # Leveraging the Definitions API | RbxNet This is documentation for RbxNet **2.0.0**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://rbxnet.australis.dev/docs/3.0/) ** (3.0.10). Version: 2.0.0 ##### caution The `Definitions` API is still very experimental, and subject to change. When designing your networking objects, it may become cumbersome to keep references to all your remotes all over the place. The standard way[#](https://rbxnet.australis.dev/docs/2.0/definitions/#the-standard-way "Direct link to heading") ------------------------------------------------------------------------------------------------------------------ You may define a remote on the server, as such: * roblox-ts * luau server/test.server.ts import Net from "@rbxts/net"; const PrintMessage \= new Net.Server.Event<\[message: string\]\>("PrintMessage"); const MakeHello \= new Net.Server.AsyncFunction<\[input: string\], \[\]\>("MakeHello"); PrintMessage.Connect((message) \=> { print(message); }); MakeHello.SetCallback((message) \=> \`Hello, ${message}!\`); Copy server/test.server.lua local Net = require(ReplicatedStorage.Net) local PrintMessage = Net.Server.Event.new("PrintMessage"); local MakeHello = Net.Server.AsyncFunction.new("MakeHello"); PrintMessage:Connect(function(message) print(message) end) MakeHello:SetCallback(function(message) return "Hello, " .. message .. "!") end) Copy And then of course, a parallel client remote on the client. * roblox-ts * luau client/test.client.ts import Net from "@rbxts/net"; const PrintMessage \= new Net.Client.Event<\[\], \[message: string\]\>("PrintMessage"); const MakeHello \= new Net.Client.AsyncFunction<\[\], \[message: string\], string\>("MakeHello"); PrintMessage.SendToServer("Hello there!"); MakeHello.CallServerAsync("Roblox").then(result \=> { print(result); // Should be Hello, Roblox! }); Copy client/test.client.ts local Net = require(ReplicatedStorage.Net) local PrintMessage = Net.Client.Event.new("PrintMessage") local MakeHello = Net.Client.AsyncFunction.new("MakeHello") PrintMessage:SendToServer("Hello there!") MakeHello:CallServerAsync("Roblox"):andThen(function(result) print(result) -- Should be Hello, Roblox! end) Copy While this works very well, you may want a single place to reference _all_ your remote objects and handle all the types for you. As you can see above, maintaining types could get very hectic. This is where `Definitions` come in. Definitions, oh my![#](https://rbxnet.australis.dev/docs/2.0/definitions/#definitions-oh-my "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------- One of the new cool features of v2.0 is the [Net.Definitions](https://rbxnet.australis.dev/docs/2.0/api/definitions) namespace. Now we can define our remotes in a single place, rather than having to maintain separate references: * roblox-ts * luau shared/remotes.ts import Net from "@rbxts/net"; const Remotes \= Net.Definitions.Create({ PrintMessage: Net.Definitions.Event<\[message: string, other: string\]\>(), MakeHello: Net.Definitions.AsyncFunction<(message: string) \=> string\>(), }); export { Remotes }; Copy And how do we use these in the client and server? server/test.server.ts import { Remotes } from "shared/remotes"; // listen to messages const PrintMessage \= Remotes.Server.Create("PrintMessage"); PrintMessage.Connect((player, message, other) \=> { print(\`Server recieved message: ${message} from player: ${player} ${other}\`); }); // listen and respond to messages const MakeHello \= Remotes.Server.Create("MakeHello"); MakeHello.SetCallback((player, message) \=> { print(\`Server got an async message from ${player} containing the message ${message}\`); return \`Hello, ${player}! We got your message: ${message}\`; }); Copy client/test.client.ts import { Remotes } from "shared/remotes"; // send a message to the server const PrintMessage \= Remotes.Client.Get("PrintMessage"); PrintMessage.SendToServer("Hello there!", "other"); // send a message to the server, while listening for a response const MakeHello \= Remotes.Client.Get("MakeHello"); MakeHello.CallServerAsync("Net is cool right??").then((result) \=> { print(\`Client got a response to the async message from server: ${result}\`); }); Copy src/shared/remotes.lua local Net = require(ReplicatedStorage.Net) local Remotes = Net.Definitions.Create({ PrintMessage = Net.Definitions.Event(), MakeHello = Net.Definitions.AsyncFunction(), }) return Remotes Copy And how do we use these in the client and server? src/server/test.server.lua local Remotes = require(ReplicatedStorage.Common.Remotes) \-- listen to messages local PrintMessage = Remotes.Server:Create("PrintMessage") PrintMessage:Connect(function (player, message, other) print("Server recieved message: ", message, "from player:" ,player, other) end) \-- listen and respond to messages local MakeHello = Remotes.Server:Create("MakeHello") MakeHello:SetCallback(function(player, message) print("Server got an async message from ", player, " containing the message ", message) return "Hello, " .. tostring(player) .. "! We got your message: " .. message end) Copy client/test.client.lua local Remotes = require(ReplicatedStorage.Common.Remotes) \-- send a message to the server local PrintMessage = Remotes.Client:Get("PrintMessage"); PrintMessage:SendToServer("Hello there!", "other"); \-- send a message to the server, while listening for a response local MakeHello = Remotes.Client:Get("MakeHello") MakeHello:CallServerAsync("Net is cool right??"):andThen(function(result) print("Client got a response to the async message from server", result) end) Copy Simple! note the lack of needing type information outside of the definitions file. If you want to use your definitions in multiple places, you don't have to worry about your types being out of sync! [Edit this page](https://github.com/roblox-aurora/rbx-net/edit/main/docs/versioned_docs/version-2.0.x/guides/definitions.md) * [The standard way](https://rbxnet.australis.dev/docs/2.0/definitions/#the-standard-way) * [Definitions, oh my!](https://rbxnet.australis.dev/docs/2.0/definitions/#definitions-oh-my) --- # Page Not Found | RbxNet Page Not Found ============== We could not find what you were looking for. Please contact the owner of the site that linked you to the original URL and let them know their link is broken. --- # Page Not Found | RbxNet Page Not Found ============== We could not find what you were looking for. Please contact the owner of the site that linked you to the original URL and let them know their link is broken. --- # Page Not Found | RbxNet Page Not Found ============== We could not find what you were looking for. Please contact the owner of the site that linked you to the original URL and let them know their link is broken. --- # Page Not Found | RbxNet Page Not Found ============== We could not find what you were looking for. Please contact the owner of the site that linked you to the original URL and let them know their link is broken. ---