mirror of
https://github.com/rilaxik/fivem-rpc.git
synced 2026-09-28 01:29:13 +00:00
docs: TSdoc
This commit is contained in:
+10
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||
"plugins": ["eslint", "typescript", "unicorn", "oxc", "import"],
|
||||
"plugins": ["eslint", "typescript", "unicorn", "oxc", "import", "jsdoc"],
|
||||
"categories": {
|
||||
"correctness": "error",
|
||||
"suspicious": "warn"
|
||||
@@ -8,7 +8,15 @@
|
||||
"rules": {
|
||||
"typescript/no-explicit-any": "error",
|
||||
"typescript/no-unsafe-function-type": "error",
|
||||
"eslint/no-underscore-dangle": "off"
|
||||
"eslint/no-underscore-dangle": "off",
|
||||
"jsdoc/check-tag-names": [
|
||||
"error",
|
||||
{ "typed": true, "definedTags": ["defaultValue", "remarks", "typeParam"] }
|
||||
],
|
||||
"jsdoc/empty-tags": "error",
|
||||
"jsdoc/no-blank-blocks": "error",
|
||||
"jsdoc/require-param-description": "error",
|
||||
"jsdoc/require-param-name": "error"
|
||||
},
|
||||
"ignorePatterns": ["**/dist"]
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ import {
|
||||
type RPCStateRaw,
|
||||
} from '../utils/types'
|
||||
|
||||
/**
|
||||
* **Internal** Shared by `RPCInstanceServer`, `RPCInstanceClient` and
|
||||
* `RPCInstanceWebview`.
|
||||
*/
|
||||
export class RPCInstanceBase {
|
||||
protected readonly env: RPCEnvironment
|
||||
protected readonly debug: boolean
|
||||
|
||||
@@ -26,6 +26,18 @@ import type {
|
||||
} from '../utils/typing'
|
||||
import { RPCInstanceBase } from './base'
|
||||
|
||||
/**
|
||||
* RPC instance for client code, returned by `createRPC({ env: 'client' })`.
|
||||
* Create one per client and import it from your own module.
|
||||
*
|
||||
* - `on*` registers the listener that answers calls from one direction. One
|
||||
* listener per event: registering the same name again replaces it, `off*`
|
||||
* removes it
|
||||
* - `emit*` calls the listener on the target and resolves with its return
|
||||
* value, or rejects with {@link RPCError}
|
||||
* - also relays calls between its webview and the server, so every client
|
||||
* needs an instance even without listeners of its own
|
||||
*/
|
||||
export class RPCInstanceClient extends RPCInstanceBase {
|
||||
private readonly _emitterServer: Emitter
|
||||
private readonly _emitterWeb: Emitter
|
||||
@@ -123,6 +135,16 @@ export class RPCInstanceClient extends RPCInstanceBase {
|
||||
|
||||
// ===== SERVER =====
|
||||
|
||||
/**
|
||||
* Listens for `emitClient` and `emitClientEveryone` calls from the server
|
||||
* (server -> client). For `emitClientEveryone` the return value is not sent.
|
||||
*
|
||||
* @param cb - gets the event arguments. Its return value (awaited) is sent
|
||||
* back to the caller
|
||||
*
|
||||
* @example
|
||||
* rpc.onServer('askTrade', offer => showTradeDialog(offer))
|
||||
*/
|
||||
public onServer<EventName extends RPCEventName<s.RPCEvents_ServerClient>>(
|
||||
eventName: EventName,
|
||||
cb: RPCListener<s.RPCEvents_ServerClient, EventName>,
|
||||
@@ -130,12 +152,23 @@ export class RPCInstanceClient extends RPCInstanceBase {
|
||||
return this.listen(this._emitterServer, 'onServer', eventName, cb)
|
||||
}
|
||||
|
||||
/** Removes the `onServer` listener for `eventName` */
|
||||
public offServer<EventName extends RPCEventName<s.RPCEvents_ServerClient>>(
|
||||
eventName: EventName,
|
||||
): this {
|
||||
return this.unlisten(this._emitterServer, 'offServer', eventName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the server's `onClient` listener (client -> server) and resolves
|
||||
* with its return value. The server listener gets this player's id first.
|
||||
*
|
||||
* @throws {@link RPCError} `EVENT_NOT_REGISTERED` (no listener),
|
||||
* `HANDLER_ERROR` (the listener threw) or `TIMEOUT`
|
||||
*
|
||||
* @example
|
||||
* const money = await rpc.emitServer('getMoney', 'bank')
|
||||
*/
|
||||
public async emitServer<
|
||||
EventName extends RPCEventName<s.RPCEvents_ClientServer>,
|
||||
>(
|
||||
@@ -151,6 +184,16 @@ export class RPCInstanceClient extends RPCInstanceBase {
|
||||
|
||||
// ===== WEBVIEW =====
|
||||
|
||||
/**
|
||||
* Listens for `emitClient` calls from this player's webview
|
||||
* (webview -> client).
|
||||
*
|
||||
* @param cb - gets the event arguments. Its return value (awaited) is sent
|
||||
* back to the caller
|
||||
*
|
||||
* @example
|
||||
* rpc.onWebview('getPosition', () => GetEntityCoords(PlayerPedId(), false))
|
||||
*/
|
||||
public onWebview<EventName extends RPCEventName<s.RPCEvents_WebviewClient>>(
|
||||
eventName: EventName,
|
||||
cb: RPCListener<s.RPCEvents_WebviewClient, EventName>,
|
||||
@@ -158,12 +201,23 @@ export class RPCInstanceClient extends RPCInstanceBase {
|
||||
return this.listen(this._emitterWeb, 'onWebview', eventName, cb)
|
||||
}
|
||||
|
||||
/** Removes the `onWebview` listener for `eventName` */
|
||||
public offWebview<EventName extends RPCEventName<s.RPCEvents_WebviewClient>>(
|
||||
eventName: EventName,
|
||||
): this {
|
||||
return this.unlisten(this._emitterWeb, 'offWebview', eventName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the `onClient` listener in this player's webview (client -> webview)
|
||||
* and resolves with its return value.
|
||||
*
|
||||
* @throws {@link RPCError} `EVENT_NOT_REGISTERED` (no listener),
|
||||
* `HANDLER_ERROR` (the listener threw) or `TIMEOUT`
|
||||
*
|
||||
* @example
|
||||
* const choice = await rpc.emitWebview('openMenu', items)
|
||||
*/
|
||||
public async emitWebview<
|
||||
EventName extends RPCEventName<s.RPCEvents_ClientWebview>,
|
||||
>(
|
||||
@@ -182,6 +236,15 @@ export class RPCInstanceClient extends RPCInstanceBase {
|
||||
|
||||
// ===== SELF =====
|
||||
|
||||
/**
|
||||
* Listens for `emitSelf` calls in this environment (client -> client).
|
||||
*
|
||||
* @param cb - gets the event arguments. Its return value (awaited) is sent
|
||||
* back to the caller
|
||||
*
|
||||
* @example
|
||||
* rpc.onSelf('add', (a, b) => a + b)
|
||||
*/
|
||||
public onSelf<EventName extends RPCEventName<s.RPCEvents_Client>>(
|
||||
eventName: EventName,
|
||||
cb: RPCListener<s.RPCEvents_Client, EventName>,
|
||||
@@ -189,12 +252,23 @@ export class RPCInstanceClient extends RPCInstanceBase {
|
||||
return this.listen(this._emitterLocal, 'onSelf', eventName, cb)
|
||||
}
|
||||
|
||||
/** Removes the `onSelf` listener for `eventName` */
|
||||
public offSelf<EventName extends RPCEventName<s.RPCEvents_Client>>(
|
||||
eventName: EventName,
|
||||
): this {
|
||||
return this.unlisten(this._emitterLocal, 'offSelf', eventName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls this environment's own `onSelf` listener directly and resolves with
|
||||
* its return value. No timeout; errors thrown by the listener reach the caller
|
||||
* unchanged.
|
||||
*
|
||||
* @throws {@link RPCError} `EVENT_NOT_REGISTERED` if no `onSelf` listener exists
|
||||
*
|
||||
* @example
|
||||
* const total = await rpc.emitSelf('add', 2, 3)
|
||||
*/
|
||||
public async emitSelf<EventName extends RPCEventName<s.RPCEvents_Client>>(
|
||||
eventName: EventName,
|
||||
...args: RPCEventArgs<s.RPCEvents_Client, EventName>
|
||||
@@ -204,6 +278,15 @@ export class RPCInstanceClient extends RPCInstanceBase {
|
||||
|
||||
// ===== OTHER =====
|
||||
|
||||
/**
|
||||
* Registers a chat command (FiveM `RegisterCommand`).
|
||||
*
|
||||
* @param cb - gets FiveM's `source`, the strings typed after the command and
|
||||
* the full command line. Validate `args` yourself
|
||||
*
|
||||
* @example
|
||||
* rpc.onCommand('coords', () => console.log(GetEntityCoords(PlayerPedId(), false)))
|
||||
*/
|
||||
public onCommand<CommandName extends RPCCommandName<s.RPCCommands_Client>>(
|
||||
command: CommandName,
|
||||
cb: (player: number, args: string[], rawCommand: string) => void,
|
||||
@@ -215,6 +298,15 @@ export class RPCInstanceClient extends RPCInstanceBase {
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to a native FiveM client event, e.g. `entityDamaged`.
|
||||
*
|
||||
* @throws {@link RPCError} `UNKNOWN_NATIVE` if `eventName` is not in
|
||||
* `NATIVE_CLIENT_EVENTS`. Register other events with FiveM's `on` directly
|
||||
*
|
||||
* @example
|
||||
* rpc.onNativeEvent('entityDamaged', (victim, culprit) => console.log(victim))
|
||||
*/
|
||||
public onNativeEvent<EventName extends keyof RPCNativeClientEvents>(
|
||||
eventName: EventName,
|
||||
cb: (...args: Parameters<RPCNativeClientEvents[EventName]>) => void,
|
||||
@@ -233,6 +325,16 @@ export class RPCInstanceClient extends RPCInstanceBase {
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to a native game event, e.g. `CEventShockingCarCrash`.
|
||||
*
|
||||
* @throws {@link RPCError} `UNKNOWN_NATIVE` if `eventName` is not in
|
||||
* `NATIVE_CLIENT_NETWORK_EVENTS`. Register other events with FiveM's `on`
|
||||
* directly
|
||||
*
|
||||
* @example
|
||||
* rpc.onNativeNetworkEvent('CEventShockingCarCrash', (entities, eventEntity) => {})
|
||||
*/
|
||||
public onNativeNetworkEvent<
|
||||
EventName extends keyof RPCNativeClientNetworkEvents,
|
||||
>(
|
||||
@@ -253,6 +355,15 @@ export class RPCInstanceClient extends RPCInstanceBase {
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses this player's webview (FiveM `SetNuiFocus`).
|
||||
*
|
||||
* @param hasFocus - the webview receives keyboard input
|
||||
* @param hasCursor - the mouse cursor is shown
|
||||
*
|
||||
* @example
|
||||
* rpc.setWebviewFocus(true, true)
|
||||
*/
|
||||
public setWebviewFocus(hasFocus: boolean, hasCursor: boolean): this {
|
||||
this.log(`setWebviewFocus ${hasFocus} ${hasCursor}`)
|
||||
|
||||
|
||||
+107
-1
@@ -20,6 +20,18 @@ import type {
|
||||
} from '../utils/typing'
|
||||
import { RPCInstanceBase } from './base'
|
||||
|
||||
/**
|
||||
* RPC instance for server code, returned by `createRPC({ env: 'server' })`.
|
||||
* Create one per server and import it from your own module.
|
||||
*
|
||||
* - `on*` registers the listener that answers calls from one direction. One
|
||||
* listener per event: registering the same name again replaces it, `off*`
|
||||
* removes it
|
||||
* - `emit*` calls the listener on the target and resolves with its return
|
||||
* value, or rejects with {@link RPCError}
|
||||
* - listeners for client and webview calls get the calling player's server id
|
||||
* first, taken from FiveM `source`
|
||||
*/
|
||||
export class RPCInstanceServer extends RPCInstanceBase {
|
||||
private readonly _emitterClient: Emitter
|
||||
private readonly _emitterWeb: Emitter
|
||||
@@ -75,6 +87,16 @@ export class RPCInstanceServer extends RPCInstanceBase {
|
||||
|
||||
// ===== CLIENT =====
|
||||
|
||||
/**
|
||||
* Listens for `emitServer` calls from clients (client -> server).
|
||||
*
|
||||
* @param cb - gets the calling player's server id first (from FiveM
|
||||
* `source`, never from the payload), then the event arguments. Its return
|
||||
* value (awaited) is sent back to the caller
|
||||
*
|
||||
* @example
|
||||
* rpc.onClient('getMoney', (player, account) => getMoney(player, account))
|
||||
*/
|
||||
public onClient<EventName extends RPCEventName<s.RPCEvents_ClientServer>>(
|
||||
eventName: EventName,
|
||||
cb: RPCListener<s.RPCEvents_ClientServer, EventName, [player: number]>,
|
||||
@@ -82,12 +104,24 @@ export class RPCInstanceServer extends RPCInstanceBase {
|
||||
return this.listen(this._emitterClient, 'onClient', eventName, cb)
|
||||
}
|
||||
|
||||
/** Removes the `onClient` listener for `eventName` */
|
||||
public offClient<EventName extends RPCEventName<s.RPCEvents_ClientServer>>(
|
||||
eventName: EventName,
|
||||
): this {
|
||||
return this.unlisten(this._emitterClient, 'offClient', eventName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the `onServer` listener on one client (server -> client) and
|
||||
* resolves with its return value.
|
||||
*
|
||||
* @param player - server id of the target player
|
||||
* @throws {@link RPCError} `EVENT_NOT_REGISTERED` (no listener),
|
||||
* `HANDLER_ERROR` (the listener threw) or `TIMEOUT`
|
||||
*
|
||||
* @example
|
||||
* const accepted = await rpc.emitClient(player, 'askTrade', offer)
|
||||
*/
|
||||
public async emitClient<
|
||||
EventName extends RPCEventName<s.RPCEvents_ServerClient>,
|
||||
>(
|
||||
@@ -102,6 +136,14 @@ export class RPCInstanceServer extends RPCInstanceBase {
|
||||
return this._pending.wait(payload, player)
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the `onServer` listener on every client (server -> all clients).
|
||||
* One-way: resolves once sent, clients do not answer and their failures stay
|
||||
* on the client.
|
||||
*
|
||||
* @example
|
||||
* await rpc.emitClientEveryone('weatherChanged', 'RAIN')
|
||||
*/
|
||||
public async emitClientEveryone<
|
||||
EventName extends RPCEventName<s.RPCEvents_ServerClient>,
|
||||
>(
|
||||
@@ -115,6 +157,17 @@ export class RPCInstanceServer extends RPCInstanceBase {
|
||||
|
||||
// ===== WEBVIEW =====
|
||||
|
||||
/**
|
||||
* Listens for `emitServer` calls from webviews (webview -> server, relayed
|
||||
* by the player's client).
|
||||
*
|
||||
* @param cb - gets the calling player's server id first (from FiveM
|
||||
* `source`, never from the payload), then the event arguments. Its return
|
||||
* value (awaited) is sent back to the caller
|
||||
*
|
||||
* @example
|
||||
* rpc.onWebview('buyItem', (player, item) => shop.buy(player, item))
|
||||
*/
|
||||
public onWebview<EventName extends RPCEventName<s.RPCEvents_WebviewServer>>(
|
||||
eventName: EventName,
|
||||
cb: RPCListener<s.RPCEvents_WebviewServer, EventName, [player: number]>,
|
||||
@@ -122,12 +175,24 @@ export class RPCInstanceServer extends RPCInstanceBase {
|
||||
return this.listen(this._emitterWeb, 'onWebview', eventName, cb)
|
||||
}
|
||||
|
||||
/** Removes the `onWebview` listener for `eventName` */
|
||||
public offWebview<EventName extends RPCEventName<s.RPCEvents_WebviewServer>>(
|
||||
eventName: EventName,
|
||||
): this {
|
||||
return this.unlisten(this._emitterWeb, 'offWebview', eventName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the `onServer` listener in one player's webview (server -> webview,
|
||||
* relayed by that player's client) and resolves with its return value.
|
||||
*
|
||||
* @param player - server id of the target player
|
||||
* @throws {@link RPCError} `EVENT_NOT_REGISTERED` (no listener),
|
||||
* `HANDLER_ERROR` (the listener threw) or `TIMEOUT`
|
||||
*
|
||||
* @example
|
||||
* const confirmed = await rpc.emitWebview(player, 'confirmPurchase', item)
|
||||
*/
|
||||
public async emitWebview<
|
||||
EventName extends RPCEventName<s.RPCEvents_ServerWebview>,
|
||||
>(
|
||||
@@ -144,19 +209,39 @@ export class RPCInstanceServer extends RPCInstanceBase {
|
||||
|
||||
// ===== SELF =====
|
||||
|
||||
/**
|
||||
* Listens for `emitSelf` calls in this environment (server -> server).
|
||||
*
|
||||
* @param cb - gets the event arguments. Its return value (awaited) is sent
|
||||
* back to the caller
|
||||
*
|
||||
* @example
|
||||
* rpc.onSelf('add', (a, b) => a + b)
|
||||
*/
|
||||
public onSelf<EventName extends RPCEventName<s.RPCEvents_Server>>(
|
||||
eventName: EventName,
|
||||
cb: RPCListener<s.RPCEvents_Server, EventName, [player: number]>,
|
||||
cb: RPCListener<s.RPCEvents_Server, EventName>,
|
||||
): this {
|
||||
return this.listen(this._emitterLocal, 'onSelf', eventName, cb)
|
||||
}
|
||||
|
||||
/** Removes the `onSelf` listener for `eventName` */
|
||||
public offSelf<EventName extends RPCEventName<s.RPCEvents_Server>>(
|
||||
eventName: EventName,
|
||||
): this {
|
||||
return this.unlisten(this._emitterLocal, 'offSelf', eventName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls this environment's own `onSelf` listener directly and resolves with
|
||||
* its return value. No timeout; errors thrown by the listener reach the caller
|
||||
* unchanged.
|
||||
*
|
||||
* @throws {@link RPCError} `EVENT_NOT_REGISTERED` if no `onSelf` listener exists
|
||||
*
|
||||
* @example
|
||||
* const total = await rpc.emitSelf('add', 2, 3)
|
||||
*/
|
||||
public async emitSelf<EventName extends RPCEventName<s.RPCEvents_Server>>(
|
||||
eventName: EventName,
|
||||
...args: RPCEventArgs<s.RPCEvents_Server, EventName>
|
||||
@@ -166,6 +251,18 @@ export class RPCInstanceServer extends RPCInstanceBase {
|
||||
|
||||
// ===== OTHER =====
|
||||
|
||||
/**
|
||||
* Registers a chat command (FiveM `RegisterCommand`).
|
||||
*
|
||||
* @param cb - gets the player's server id (`0` for the server console), the
|
||||
* strings typed after the command and the full command line. Validate
|
||||
* `args` yourself
|
||||
* @param restricted - only players with the ACE permission `command.<name>`
|
||||
* can use it
|
||||
*
|
||||
* @example
|
||||
* rpc.onCommand('heal', (player, args) => heal(player, Number(args[0])), true)
|
||||
*/
|
||||
public onCommand<CommandName extends RPCCommandName<s.RPCCommands_Server>>(
|
||||
command: CommandName,
|
||||
cb: (player: number, args: string[], rawCommand: string) => void,
|
||||
@@ -178,6 +275,15 @@ export class RPCInstanceServer extends RPCInstanceBase {
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to a native FiveM server event, e.g. `playerJoining`.
|
||||
*
|
||||
* @throws {@link RPCError} `UNKNOWN_NATIVE` if `eventName` is not in
|
||||
* `NATIVE_SERVER_EVENTS`. Register other events with FiveM's `on` directly
|
||||
*
|
||||
* @example
|
||||
* rpc.onNativeEvent('playerJoining', (source, oldId) => console.log(source))
|
||||
*/
|
||||
public onNativeEvent<EventName extends keyof RPCNativeServerEvents>(
|
||||
eventName: EventName,
|
||||
cb: (...args: Parameters<RPCNativeServerEvents[EventName]>) => void,
|
||||
|
||||
@@ -16,6 +16,18 @@ import type {
|
||||
} from '../utils/typing'
|
||||
import { RPCInstanceBase } from './base'
|
||||
|
||||
/**
|
||||
* RPC instance for webview code, returned by `createRPC({ env: 'webview' })`.
|
||||
* Create one per webview and import it from your own module.
|
||||
*
|
||||
* - `on*` registers the listener that answers calls from one direction. One
|
||||
* listener per event: registering the same name again replaces it, `off*`
|
||||
* removes it
|
||||
* - `emit*` calls the listener on the target and resolves with its return
|
||||
* value, or rejects with {@link RPCError}
|
||||
* - calls to and from the server are relayed by the player's client, which
|
||||
* must run `createRPC({ env: 'client' })`
|
||||
*/
|
||||
export class RPCInstanceWebview extends RPCInstanceBase {
|
||||
private readonly _emitterClient: Emitter
|
||||
private readonly _emitterServer: Emitter
|
||||
@@ -69,6 +81,16 @@ export class RPCInstanceWebview extends RPCInstanceBase {
|
||||
|
||||
// ===== CLIENT =====
|
||||
|
||||
/**
|
||||
* Listens for `emitWebview` calls from this player's client
|
||||
* (client -> webview).
|
||||
*
|
||||
* @param cb - gets the event arguments. Its return value (awaited) is sent
|
||||
* back to the caller
|
||||
*
|
||||
* @example
|
||||
* rpc.onClient('openMenu', items => menu.open(items))
|
||||
*/
|
||||
public onClient<EventName extends RPCEventName<s.RPCEvents_ClientWebview>>(
|
||||
eventName: EventName,
|
||||
cb: RPCListener<s.RPCEvents_ClientWebview, EventName>,
|
||||
@@ -76,12 +98,23 @@ export class RPCInstanceWebview extends RPCInstanceBase {
|
||||
return this.listen(this._emitterClient, 'onClient', eventName, cb)
|
||||
}
|
||||
|
||||
/** Removes the `onClient` listener for `eventName` */
|
||||
public offClient<EventName extends RPCEventName<s.RPCEvents_ClientWebview>>(
|
||||
eventName: EventName,
|
||||
): this {
|
||||
return this.unlisten(this._emitterClient, 'offClient', eventName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the client's `onWebview` listener (webview -> client) and resolves
|
||||
* with its return value.
|
||||
*
|
||||
* @throws {@link RPCError} `EVENT_NOT_REGISTERED` (no listener),
|
||||
* `HANDLER_ERROR` (the listener threw) or `TIMEOUT`
|
||||
*
|
||||
* @example
|
||||
* const position = await rpc.emitClient('getPosition')
|
||||
*/
|
||||
public async emitClient<
|
||||
EventName extends RPCEventName<s.RPCEvents_WebviewClient>,
|
||||
>(
|
||||
@@ -95,6 +128,16 @@ export class RPCInstanceWebview extends RPCInstanceBase {
|
||||
|
||||
// ===== SERVER =====
|
||||
|
||||
/**
|
||||
* Listens for `emitWebview` calls from the server (server -> webview,
|
||||
* relayed by the client).
|
||||
*
|
||||
* @param cb - gets the event arguments. Its return value (awaited) is sent
|
||||
* back to the caller
|
||||
*
|
||||
* @example
|
||||
* rpc.onServer('confirmPurchase', item => window.confirm(`Buy ${item}?`))
|
||||
*/
|
||||
public onServer<EventName extends RPCEventName<s.RPCEvents_ServerWebview>>(
|
||||
eventName: EventName,
|
||||
cb: RPCListener<s.RPCEvents_ServerWebview, EventName>,
|
||||
@@ -102,12 +145,24 @@ export class RPCInstanceWebview extends RPCInstanceBase {
|
||||
return this.listen(this._emitterServer, 'onServer', eventName, cb)
|
||||
}
|
||||
|
||||
/** Removes the `onServer` listener for `eventName` */
|
||||
public offServer<EventName extends RPCEventName<s.RPCEvents_ServerWebview>>(
|
||||
eventName: EventName,
|
||||
): this {
|
||||
return this.unlisten(this._emitterServer, 'offServer', eventName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the server's `onWebview` listener (webview -> server, relayed by
|
||||
* the client) and resolves with its return value. The server listener gets
|
||||
* this player's id first.
|
||||
*
|
||||
* @throws {@link RPCError} `EVENT_NOT_REGISTERED` (no listener),
|
||||
* `HANDLER_ERROR` (the listener threw) or `TIMEOUT`
|
||||
*
|
||||
* @example
|
||||
* const bought = await rpc.emitServer('buyItem', 'water')
|
||||
*/
|
||||
public async emitServer<
|
||||
EventName extends RPCEventName<s.RPCEvents_WebviewServer>,
|
||||
>(
|
||||
@@ -121,6 +176,15 @@ export class RPCInstanceWebview extends RPCInstanceBase {
|
||||
|
||||
// ===== SELF =====
|
||||
|
||||
/**
|
||||
* Listens for `emitSelf` calls in this environment (webview -> webview).
|
||||
*
|
||||
* @param cb - gets the event arguments. Its return value (awaited) is sent
|
||||
* back to the caller
|
||||
*
|
||||
* @example
|
||||
* rpc.onSelf('add', (a, b) => a + b)
|
||||
*/
|
||||
public onSelf<EventName extends RPCEventName<s.RPCEvents_Webview>>(
|
||||
eventName: EventName,
|
||||
cb: RPCListener<s.RPCEvents_Webview, EventName>,
|
||||
@@ -128,12 +192,23 @@ export class RPCInstanceWebview extends RPCInstanceBase {
|
||||
return this.listen(this._emitterLocal, 'onSelf', eventName, cb)
|
||||
}
|
||||
|
||||
/** Removes the `onSelf` listener for `eventName` */
|
||||
public offSelf<EventName extends RPCEventName<s.RPCEvents_Webview>>(
|
||||
eventName: EventName,
|
||||
): this {
|
||||
return this.unlisten(this._emitterLocal, 'offSelf', eventName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls this environment's own `onSelf` listener directly and resolves with
|
||||
* its return value. No timeout; errors thrown by the listener reach the caller
|
||||
* unchanged.
|
||||
*
|
||||
* @throws {@link RPCError} `EVENT_NOT_REGISTERED` if no `onSelf` listener exists
|
||||
*
|
||||
* @example
|
||||
* const total = await rpc.emitSelf('add', 2, 3)
|
||||
*/
|
||||
public async emitSelf<EventName extends RPCEventName<s.RPCEvents_Webview>>(
|
||||
eventName: EventName,
|
||||
...args: RPCEventArgs<s.RPCEvents_Webview, EventName>
|
||||
|
||||
@@ -12,7 +12,11 @@ import {
|
||||
/**
|
||||
* Creates the RPC instance for one environment. Create exactly one per
|
||||
* environment (server, client, webview) and export it from a local module.
|
||||
* Every client needs one, even without listeners: it relays calls between
|
||||
* its webview and the server.
|
||||
*
|
||||
* @returns `RPCInstanceServer`, `RPCInstanceClient` or `RPCInstanceWebview`,
|
||||
* matching `config.env`
|
||||
* @throws {@link RPCError} `UNKNOWN_ENVIRONMENT` if `config.env` is not
|
||||
* `'server'`, `'client'` or `'webview'`
|
||||
*
|
||||
|
||||
@@ -23,7 +23,10 @@ const serverEvents = {
|
||||
weaponDamageEvent: true,
|
||||
} satisfies Record<keyof RPCNativeServerEvents, true>
|
||||
|
||||
/** https://docs.fivem.net/docs/scripting-reference/events/server-events/ */
|
||||
/**
|
||||
* Events `onNativeEvent` accepts on the server:
|
||||
* https://docs.fivem.net/docs/scripting-reference/events/server-events/
|
||||
*/
|
||||
export const NATIVE_SERVER_EVENTS = Object.keys(
|
||||
serverEvents,
|
||||
) as readonly (keyof RPCNativeServerEvents)[]
|
||||
@@ -41,12 +44,16 @@ const clientEvents = {
|
||||
populationPedCreating: true,
|
||||
} satisfies Record<keyof RPCNativeClientEvents, true>
|
||||
|
||||
/** https://docs.fivem.net/docs/scripting-reference/events/client-events/ */
|
||||
/**
|
||||
* Events `onNativeEvent` accepts on the client:
|
||||
* https://docs.fivem.net/docs/scripting-reference/events/client-events/
|
||||
*/
|
||||
export const NATIVE_CLIENT_EVENTS = Object.keys(
|
||||
clientEvents,
|
||||
) as readonly (keyof RPCNativeClientEvents)[]
|
||||
|
||||
/**
|
||||
* Events `onNativeNetworkEvent` accepts on the client:
|
||||
* https://docs.fivem.net/docs/game-references/game-events/
|
||||
*
|
||||
* Source of truth for `RPCNativeClientNetworkEventsNames`.
|
||||
|
||||
+15
-5
@@ -4,7 +4,8 @@ import type { RPCInstanceWebview } from '../core/webview'
|
||||
import type { NATIVE_CLIENT_NETWORK_EVENTS } from './native'
|
||||
|
||||
/**
|
||||
* Possible environment states for `RPCConfig`
|
||||
* Where an instance runs: `server` (server scripts), `client` (client
|
||||
* scripts) or `webview` (NUI page)
|
||||
*/
|
||||
export type RPCEnvironment = 'server' | 'client' | 'webview'
|
||||
|
||||
@@ -99,18 +100,22 @@ export enum RPCEvents {
|
||||
LISTENER_WEB = '__rpc:listenerWeb',
|
||||
}
|
||||
|
||||
/**
|
||||
* Errors to check against
|
||||
*/
|
||||
/** Values of `RPCError.code` */
|
||||
export enum RPCErrors {
|
||||
/** The target has no listener for the event (or `emitSelf` has no `onSelf`) */
|
||||
EVENT_NOT_REGISTERED = 'Event not registered',
|
||||
/** `onNative*` got an event that is not in its `NATIVE_*` list */
|
||||
UNKNOWN_NATIVE = 'Unknown native event',
|
||||
/** `createRPC` got an `env` other than server, client or webview */
|
||||
UNKNOWN_ENVIRONMENT = 'Unknown environment',
|
||||
/** No response within `RPCConfig.timeout` */
|
||||
TIMEOUT = 'Timed out waiting for response',
|
||||
/** The listener on the target threw; the message carries its error */
|
||||
HANDLER_ERROR = 'Listener threw an error',
|
||||
}
|
||||
|
||||
/**
|
||||
* Native server events accepted by `onNativeEvent` on the server:
|
||||
* https://docs.fivem.net/docs/scripting-reference/events/server-events/
|
||||
*/
|
||||
export type RPCNativeServerEvents = {
|
||||
@@ -245,6 +250,7 @@ export type RPCNativeServerEvents = {
|
||||
}
|
||||
|
||||
/**
|
||||
* Native client events accepted by `onNativeEvent` on the client:
|
||||
* https://docs.fivem.net/docs/scripting-reference/events/client-events/
|
||||
*/
|
||||
export type RPCNativeClientEvents = {
|
||||
@@ -277,6 +283,7 @@ export type RPCNativeClientEvents = {
|
||||
): void
|
||||
}
|
||||
|
||||
/** Game events accepted by `onNativeNetworkEvent` on the client */
|
||||
export type RPCNativeClientNetworkEvents = {
|
||||
[name in RPCNativeClientNetworkEventsNames]: (
|
||||
entities: number[],
|
||||
@@ -285,6 +292,9 @@ export type RPCNativeClientNetworkEvents = {
|
||||
) => void
|
||||
}
|
||||
|
||||
/** https://docs.fivem.net/docs/game-references/game-events/ */
|
||||
/**
|
||||
* Names in `NATIVE_CLIENT_NETWORK_EVENTS`:
|
||||
* https://docs.fivem.net/docs/game-references/game-events/
|
||||
*/
|
||||
export type RPCNativeClientNetworkEventsNames =
|
||||
(typeof NATIVE_CLIENT_NETWORK_EVENTS)[number]
|
||||
|
||||
@@ -67,7 +67,7 @@ Each interface is one direction. An interface you leave empty stays loose (any n
|
||||
| `RPCCommands_Client` | - | - | `onCommand` (client) |
|
||||
| `RPCCommands_Server` | - | - | `onCommand` (server) |
|
||||
|
||||
- events: the member name is the event name, its parameters are the arguments, its return type is what `emit*` resolves with. Server listeners get the player id before the declared arguments. Names that are not identifiers work too: `'buy-item'(item: string): boolean`
|
||||
- events: the member name is the event name, its parameters are the arguments, its return type is what `emit*` resolves with. Server `onClient` and `onWebview` listeners get the player id before the declared arguments. Names that are not identifiers work too: `'buy-item'(item: string): boolean`
|
||||
- commands: the key is the command name, the value is not used (`true`)
|
||||
|
||||
## License
|
||||
|
||||
Reference in New Issue
Block a user