From 8fe181a2fdf04348e4e96c943981466d561a0ebc Mon Sep 17 00:00:00 2001 From: Charles Kim <52868068+charleskimbac@users.noreply.github.com> Date: Tue, 15 Jul 2025 04:23:49 -0400 Subject: [PATCH 1/8] grammar fix --- docs/guides/lifecycle-events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/lifecycle-events.md b/docs/guides/lifecycle-events.md index b072034..89aba03 100644 --- a/docs/guides/lifecycle-events.md +++ b/docs/guides/lifecycle-events.md @@ -30,7 +30,7 @@ It runs after physics has been done and is optimal for responding to changes in The OnPhysics event is a lifecycle event that is directly connected to the RunService.Stepped event. -It runs prior to physics has been done and is optimal for manipulating physics. +It runs prior to physics being done and is optimal for manipulating physics. ## OnRender (Singletons, Components) From a5ea0a278aaeb120964ecba8b192fbe599450c57 Mon Sep 17 00:00:00 2001 From: Charles Kim <52868068+charleskimbac@users.noreply.github.com> Date: Wed, 16 Jul 2025 14:10:24 -0400 Subject: [PATCH 2/8] add namespaces in features, rm "Re-exporting" section --- .../networking/introduction.md | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/docs/additional-modules/networking/introduction.md b/docs/additional-modules/networking/introduction.md index 2cd406a..8b999ff 100644 --- a/docs/additional-modules/networking/introduction.md +++ b/docs/additional-modules/networking/introduction.md @@ -10,26 +10,8 @@ Flamework's networking is designed with ease of use and convenience in mind. - Two way communication between the server and client. - [Middleware](./middleware) - Modify, delay or drop requests on the receiver before being passed to handlers. +- [Namespaces](./namespaces) + - Organize your remote events and remote functions into groups. - Automatic type guards - Declare the event and let Flamework handle the rest ~~(except writing your code)~~! - -## Re-exporting -After you've defined your networking events and/or functions, you'll want to export the created `server` and `client` objects in separate files. - -If you use the [roblox-ts vscode extension](https://marketplace.visualstudio.com/items?itemName=roblox-ts.vscode-roblox-ts) then the intellisense will hide the server objects on the client and vice-versa. - -This will also allow you to hide server-specific configuration (such as generated type guards or middleware) from the client, for additional security. - -```ts -// Assumes your GlobalEvents/GlobalFunctions object is in shared/networking.ts -import { GlobalEvents } from "shared/networking"; -import { GlobalFunctions } from "shared/networking"; - -// client/networking.ts -export const Events = GlobalEvents.createClient(); -export const Functions = GlobalFunctions.createClient(); - -// server/networking.ts -export const Events = GlobalEvents.createServer(); -export const Functions = GlobalFunctions.createServer(); -``` + From 4016098ba004ed29a53d4607b1ef82c9a7e3cf62 Mon Sep 17 00:00:00 2001 From: Charles Kim <52868068+charleskimbac@users.noreply.github.com> Date: Wed, 16 Jul 2025 19:42:06 -0400 Subject: [PATCH 3/8] explicitly state whether example code is on the server or client; typo fixes --- .../networking/remote-events.md | 65 +++++++++++++------ 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/docs/additional-modules/networking/remote-events.md b/docs/additional-modules/networking/remote-events.md index 05b34be..1223950 100644 --- a/docs/additional-modules/networking/remote-events.md +++ b/docs/additional-modules/networking/remote-events.md @@ -10,20 +10,21 @@ It should be noted that you cannot return a value from an event and the return t If you want two way communication then you should use [RemoteFunctions](./remote-functions). ```ts +// shared/networking.ts import { Networking } from "@flamework/networking"; interface ClientToServerEvents { - event(param1: string): void; + myClientToServerEvent(param1: string): void; } interface ServerToClientEvents { - event(param1: string): void; + myServerToClientEvent(param1: string): void; } -// Returns an object containing a `server` and `client` field. +// Returns an object containing the `createServer` and `createClient` fields. export const GlobalEvents = Networking.createEvent(); -// It is recommended that you create these in separate server/client files, +// It is recommended that you call `createServer` and `createClient` on the server and client respectively, // which will avoid exposing server configuration (including type guards) to the client. export const ServerEvents = GlobalEvents.createServer({ /* server config */ }); export const ClientEvents = GlobalEvents.createClient({ /* client config */ }); @@ -31,7 +32,7 @@ export const ClientEvents = GlobalEvents.createClient({ /* client config */ }); ### Unreliable Events Flamework supports specifying [unreliable remote events](https://create.roblox.com/docs/reference/engine/classes/UnreliableRemoteEvent). -These events must still follow any limits specified by Roblox (e.g the 900 byte size limit.) +These events must still follow any limits specified by Roblox (e.g the 1000 byte size limit). You can specify that an event is unreliable using the `Networking.Unreliable` type. @@ -42,55 +43,77 @@ interface ClientToServerEvents { ``` ## Using Events -Once you've declared all your events, it's time to use them. You can access your events simply by indexing the [Events](./introduction#re-exporting) object. +Once you've declared all your events, it's time to use them. You can access your events on the server or client by simply by indexing the object returned by `createServer` or `createClient` respectively. + +```ts +// server/networking.ts +import { GlobalEvents } from "shared/networking"; + +export const Events = GlobalEvents.createServer(); +export const Functions = GlobalFunctions.createServer(); +``` + +```ts +// client/networking.ts +import { GlobalEvents } from "shared/networking"; + +export const Events = GlobalEvents.createClient(); +export const Functions = GlobalFunctions.createClient(); +``` + ### Firing Events Send a request between the server and client. #### Server ```ts +import { Events } from "server/networking.ts"; + // Fire to player(s) -Events.event.fire(player, ...args); -Events.event.fire([player1, player2], ...args); +Events.myServerToClientEvent.fire(player, ...args); +Events.myServerToClientEvent.fire([player1, player2], ...args); // Fire to all players except -Events.event.except(player, ...args); -Events.event.except([player1, player2], ...args); +Events.myServerToClientEvent.except(player, ...args); +Events.myServerToClientEvent.except([player1, player2], ...args); // Broadcast -Events.event.broadcast(...args); +Events.myServerToClientEvent.broadcast(...args); // Predict, fires server event using player as the sender -Events.event.predict(player, ...args); +Events.myServerToClientEvent.predict(player, ...args); -// Shorthand syntax, equivalent to Events.event.fire -Events.event(player, ...args); +// Shorthand syntax, equivalent to Events.myServerToClientEvent.fire +Events.myServerToClientEvent(player, ...args); ``` #### Client ```ts +import { Events } from "client/networking.ts"; + // Fire to server -Events.event.fire(...args); +Events.myClientToServerEvent.fire(...args); // Predict, fires client event from the client -Events.event.predict(...args); +Events.myClientToServerEvent.predict(...args); -// Shorthand syntax, equivalent to Events.event.fire -Events.event(...args); +// Shorthand syntax, equivalent to Events.myClientToServerEvent.fire +Events.myClientToServerEvent(...args); ``` ### Connecting Connecting to an event returns a RBXScriptConnection which can be used to disconnect the event at any time. -The following example is assuming the code is run on the server. Connecting events on the server and client is identical except that clients do not have an additional `player` parameter. +Connecting events on the server and client is identical except that clients do not have an additional `player` parameter. +#### Server ```ts // Connect to an event -Events.event.connect((player, arg1) => { +Events.myServerToClientEvent.connect((player, arg1) => { print(player, arg1); }); // Disconnect an event connection -const myConnection = events.event.connect(() => {}); +const myConnection = Events.myServerToClientEvent.connect(() => {}); myConnection.Disconnect(); ``` From 2ce3b03aec4ba0b612fee365396bb0a88cc693c2 Mon Sep 17 00:00:00 2001 From: Charles Kim <52868068+charleskimbac@users.noreply.github.com> Date: Wed, 16 Jul 2025 19:56:02 -0400 Subject: [PATCH 4/8] typo fixes --- docs/additional-modules/networking/remote-events.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/additional-modules/networking/remote-events.md b/docs/additional-modules/networking/remote-events.md index 1223950..f8fe39d 100644 --- a/docs/additional-modules/networking/remote-events.md +++ b/docs/additional-modules/networking/remote-events.md @@ -25,7 +25,7 @@ interface ServerToClientEvents { export const GlobalEvents = Networking.createEvent(); // It is recommended that you call `createServer` and `createClient` on the server and client respectively, -// which will avoid exposing server configuration (including type guards) to the client. +// which will avoid exposing server configuration (including type guards) to the client. See the Using Events section below. export const ServerEvents = GlobalEvents.createServer({ /* server config */ }); export const ClientEvents = GlobalEvents.createClient({ /* client config */ }); ``` @@ -43,7 +43,7 @@ interface ClientToServerEvents { ``` ## Using Events -Once you've declared all your events, it's time to use them. You can access your events on the server or client by simply by indexing the object returned by `createServer` or `createClient` respectively. +Once you've declared all your events, it's time to use them. You can access your events on the server or client by simply indexing the object returned by `createServer` or `createClient`. ```ts // server/networking.ts From 8afdab882bc8d96c3ebb972e9cb699406c14d33e Mon Sep 17 00:00:00 2001 From: Charles Kim <52868068+charleskimbac@users.noreply.github.com> Date: Wed, 16 Jul 2025 20:09:08 -0400 Subject: [PATCH 5/8] Update remote-events.md --- docs/additional-modules/networking/remote-events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/additional-modules/networking/remote-events.md b/docs/additional-modules/networking/remote-events.md index f8fe39d..095b569 100644 --- a/docs/additional-modules/networking/remote-events.md +++ b/docs/additional-modules/networking/remote-events.md @@ -43,7 +43,7 @@ interface ClientToServerEvents { ``` ## Using Events -Once you've declared all your events, it's time to use them. You can access your events on the server or client by simply indexing the object returned by `createServer` or `createClient`. +Once you've declared all your events, it's time to use them. You can access your events on the server or client by simply indexing the object returned by `createServer` or `createClient` respectively. ```ts // server/networking.ts From f3ac7ded2522e43ce3ae92ecda92111947bdd7f0 Mon Sep 17 00:00:00 2001 From: Charles Kim <52868068+charleskimbac@users.noreply.github.com> Date: Wed, 16 Jul 2025 21:07:43 -0400 Subject: [PATCH 6/8] improved clarity --- .../networking/remote-functions.md | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/docs/additional-modules/networking/remote-functions.md b/docs/additional-modules/networking/remote-functions.md index 1a793fb..fb97ffb 100644 --- a/docs/additional-modules/networking/remote-functions.md +++ b/docs/additional-modules/networking/remote-functions.md @@ -1,50 +1,63 @@ --- title: Remote Functions --- -RemoteFunctions are for two way communicates between the server and client. This means the sender is able to receive a response from the receiver. Flamework's RemoteFunctions implementation use promises which allow you to avoid any dangerous yields, errors, etc. All requests have a timeout of 10 seconds. +RemoteFunctions are for two way communicates between the server and client. This means the sender is able to receive a response from the receiver. Flamework's RemoteFunctions implementation use promises which allow you to avoid any dangerous yields, errors, etc. All requests have a timeout of 10 seconds. Whilst it is not recommended, Flamework does support `ServerToClient` remote functions. Flamework avoids common pitfalls by implementing timeouts and cancellation (such as a player leaving) using promises. ## Creation -You can use the `Networking.createFunction` macro to create your network handler. This will contain all your events for both server and client and you can also configure your [middleware](./middleware). +You can use the `Networking.createFunction` macro to create your network handler. This will contain all your functions for both server and client and you can also configure your [middleware](./middleware). ```ts +// shared/networking.ts import { Networking } from "@flamework/networking"; interface ClientToServerFunctions { - function(param1: string): number; + myClientToServerFunction(param1: string): number; } interface ServerToClientFunctions { - function(param1: string): number; + myServerToClientFunction(param1: string): number; } -// Returns an object containing a `server` and `client` field. +// Returns an object containing the `createServer` and `createClient` fields. export const GlobalFunctions = Networking.createFunction(); -// It is recommended that you create these in separate server/client files, -// which will avoid exposing server configuration (including type guards) to the client. +// It is recommended that you call `createServer` and `createClient` on the server and client respectively, +// which will avoid exposing server configuration (including type guards) to the client. See the Using Functions section below. export const ServerFunctions = GlobalFunctions.createServer({ /* server config */ }); export const ClientFunctions = GlobalFunctions.createClient({ /* client config */ }); ``` ## Using Functions -Once you've declared all your functions, it's time to use them. You can access your functions simply by indexing the [Functions](./introduction#re-exporting) object. +Once you've declared all your functions, it's time to use them. You can access your functions by simply indexing the object returned by createServer or createClient respectively. -A `player?` parameter in the following examples means that the parameter only exists on the server, and is absent on the client. +```ts +// server/networking.ts +import { GlobalFunctions } from "shared/networking"; + +export const Functions = GlobalFunctions.createServer(); +``` + +```ts +// client/networking.ts +import { GlobalFunctions } from "shared/networking"; + +export const Functions = GlobalFunctions.createClient(); +``` ### Invoking Functions Invoke a request and wait for a response. ```ts // Invoke a function -Functions.function.invoke(player?, "my parameter!").then((value) => ...); +Functions.myFunction.invoke("my parameter!").then((value) => ...); -// Shorthand syntax, equivalent to Functions. -Functions.function(player?, "my parameter!").then((value) => ...); +// Shorthand syntax, equivalent to invoke +Functions.myFunction("my parameter!").then((value) => ...); -// Predict, simulates a request being sent -Functions.function.predict(player?, "my parameter!").then((value) => ...); +// Predict, invokes the callback +Functions.myFunction.predict("my parameter!").then((value) => ...); ``` ### Handling Functions @@ -52,14 +65,14 @@ You can only connect one handler to each function. Calling `setCallback` more th ```ts // With a normal function -Functions.function.setCallback((player?, param1) => { - print("This is", param1); +Functions.myFunction.setCallback((param1) => { + print(param1); return math.random(1, 100); }) // With an async function -Functions.function.setCallback(async (player?, param1) => { - print("This is", param1); +Functions.myFunction.setCallback(async (param1) => { + print(param1); return await myAsyncNumberGenerator(1, 100); }) ``` @@ -67,7 +80,6 @@ Functions.function.setCallback(async (player?, param1) => { ## Errors Flamework's networking exposes a `NetworkingFunctionError` enum which is used whenever a RemoteFunction request is rejected. - | Name | Description | |---------------|--------------------------------------------------------------------------------| | Timeout | The request surpassed the timeout length. | @@ -77,12 +89,11 @@ Flamework's networking exposes a `NetworkingFunctionError` enum which is used wh | Unprocessed | The request was not processed by the receiver. | ### Handling errors - Flamework's RemoteFunctions return promises which allows you to handle them the same as any other promise. Flamework always passes a `NetworkingFunctionError` as the rejection value, which tells you the reason the request failed. ```ts -Events.function.invoke() +Functions.myFunction.invoke() .then((value) => print("I successfully got", value)) .catch((reason) => { if (reason === NetworkingFunctionError.Timeout) { From f76b2f230b2571a8e8882f6c3d1f566296ab5f37 Mon Sep 17 00:00:00 2001 From: Charles Kim <52868068+charleskimbac@users.noreply.github.com> Date: Wed, 16 Jul 2025 21:09:15 -0400 Subject: [PATCH 7/8] Update remote-events.md --- docs/additional-modules/networking/remote-events.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/additional-modules/networking/remote-events.md b/docs/additional-modules/networking/remote-events.md index 095b569..1607960 100644 --- a/docs/additional-modules/networking/remote-events.md +++ b/docs/additional-modules/networking/remote-events.md @@ -50,7 +50,6 @@ Once you've declared all your events, it's time to use them. You can access your import { GlobalEvents } from "shared/networking"; export const Events = GlobalEvents.createServer(); -export const Functions = GlobalFunctions.createServer(); ``` ```ts @@ -58,10 +57,8 @@ export const Functions = GlobalFunctions.createServer(); import { GlobalEvents } from "shared/networking"; export const Events = GlobalEvents.createClient(); -export const Functions = GlobalFunctions.createClient(); ``` - ### Firing Events Send a request between the server and client. From e3bd75e05222120aa2695e8cdfb4976878653e01 Mon Sep 17 00:00:00 2001 From: Charles Kim <52868068+charleskimbac@users.noreply.github.com> Date: Fri, 18 Jul 2025 22:27:48 -0400 Subject: [PATCH 8/8] update broadcast desc --- docs/additional-modules/networking/remote-events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/additional-modules/networking/remote-events.md b/docs/additional-modules/networking/remote-events.md index 1607960..0dabd59 100644 --- a/docs/additional-modules/networking/remote-events.md +++ b/docs/additional-modules/networking/remote-events.md @@ -74,7 +74,7 @@ Events.myServerToClientEvent.fire([player1, player2], ...args); Events.myServerToClientEvent.except(player, ...args); Events.myServerToClientEvent.except([player1, player2], ...args); -// Broadcast +// Fire to all connected players Events.myServerToClientEvent.broadcast(...args); // Predict, fires server event using player as the sender