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(); -``` + diff --git a/docs/additional-modules/networking/remote-events.md b/docs/additional-modules/networking/remote-events.md index 05b34be..0dabd59 100644 --- a/docs/additional-modules/networking/remote-events.md +++ b/docs/additional-modules/networking/remote-events.md @@ -10,28 +10,29 @@ 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, -// 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 Events section below. export const ServerEvents = GlobalEvents.createServer({ /* server config */ }); 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,74 @@ 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 indexing the object returned by `createServer` or `createClient` respectively. + +```ts +// server/networking.ts +import { GlobalEvents } from "shared/networking"; + +export const Events = GlobalEvents.createServer(); +``` + +```ts +// client/networking.ts +import { GlobalEvents } from "shared/networking"; + +export const Events = GlobalEvents.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); +// Fire to all connected players +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(); ``` 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) { 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)