mirror of
https://github.com/rilaxik/fivem-rpc.git
synced 2026-09-28 01:29:13 +00:00
Compare commits
4
Commits
563ef864b7
..
v0/0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f7311ba17 | ||
|
|
00b8edc16b | ||
|
|
91a72c46e8 | ||
|
|
8a361f67ec |
@@ -0,0 +1,41 @@
|
||||
# FiveM RPC
|
||||
is an all-in-one package with asynchronous RPC implementation for FiveM servers in JS/TS
|
||||
|
||||
## Installation
|
||||
```bash
|
||||
pnpm i @entityseven/fivem-rpc
|
||||
```
|
||||
```bash
|
||||
yarn add @entityseven/fivem-rpc
|
||||
```
|
||||
```bash
|
||||
bun add @entityseven/fivem-rpc
|
||||
```
|
||||
It is highly recommended to also install additional package for enhanced typing
|
||||
```bash
|
||||
pnpm i @entityseven/fivem-rpc-shared-types -D
|
||||
```
|
||||
```bash
|
||||
yarn add @entityseven/fivem-rpc-shared-types --dev
|
||||
```
|
||||
```bash
|
||||
bun add @entityseven/fivem-rpc-shared-types -d
|
||||
```
|
||||
|
||||
## Docs
|
||||
Can be found in [/rpc/readme.md](https://github.com/rilaxik/fivem-rpc/blob/master/rpc/readme.md)
|
||||
|
||||
## Features
|
||||
- Type-Safe Development: Eliminate runtime errors and enhance code reliability with comprehensive type safety
|
||||
- All-in-one package: Communicate effortlessly between server, client and webview
|
||||
|
||||
## Contributing
|
||||
Issues and pull requests are very welcome
|
||||
|
||||
## License
|
||||
Licensed under Custom Attribution-NoDerivs Software License
|
||||
|
||||
## WIP
|
||||
- client observers to catch events between server and webview (subscribe-like behaviour)
|
||||
- client observers to prevent events (middleware-like behaviour)
|
||||
- player manager (transform player id to desired data straight from a listener)
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@entityseven/fivem-rpc",
|
||||
"description": "FiveM RPC is an abstraction for handling events in GTA V FiveM servers in JS/TS",
|
||||
"description": "FiveM RPC is an all-in-one package with asynchronous RPC implementation for FiveM servers in JS/TS",
|
||||
"version": "0.1.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
+300
@@ -0,0 +1,300 @@
|
||||
# FiveM RPC
|
||||
is an all-in package with asynchronous RPC implementation for RageMP servers in JS/TS. [Extra info](https://github.com/rilaxik/fivem-rpc/blob/master/readme.md)
|
||||
|
||||
# Motivation
|
||||
The idea was to create an extensible package, with various features to simplify the development process and provide as much comfort as possible. Inspired by usage of [altv-xrpc](https://github.com/xxshady/altv-xrpc)
|
||||
|
||||
# Installation
|
||||
```bash
|
||||
pnpm i @entityseven/fivem-rpc
|
||||
```
|
||||
```bash
|
||||
yarn add @entityseven/fivem-rpc
|
||||
```
|
||||
```bash
|
||||
bun add @entityseven/fivem-rpc
|
||||
```
|
||||
It is highly recommended to also install additional package for enhanced typing
|
||||
```bash
|
||||
pnpm i @entityseven/fivem-rpc-shared-types -D
|
||||
```
|
||||
```bash
|
||||
yarn add @entityseven/fivem-rpc-shared-types --dev
|
||||
```
|
||||
```bash
|
||||
bun add @entityseven/fivem-rpc-shared-types -d
|
||||
```
|
||||
|
||||
## Usage
|
||||
FiveM RPC is meant to be a singletone per environment. This means you _must create only one_ `RPCFactory` per your server/client/web. This also enables modifying `const rpc` to your needs, adding new methods or variables by forcing you to import it from file instead of library reference
|
||||
```ts
|
||||
// lib/rpc.ts
|
||||
import { RPCFactory } from '@entityseven/fivem-rpc'
|
||||
export const rpc = new RPCFactory(/* options */).get()
|
||||
```
|
||||
|
||||
# Docs
|
||||
|
||||
## Extras
|
||||
Along with `RPCFactory` you can also import all the types used internally, types for native client/server events and lists of native client/server events. All of that is documented in JSDoc, so no need to duplicate it here
|
||||
|
||||
## RPCConfig
|
||||
```ts
|
||||
type RPCConfig<T extends RPCEnvironment | unknown> = {
|
||||
env: T
|
||||
debug?: boolean
|
||||
}
|
||||
```
|
||||
Failing to set `env` to provided type will result in `RPCErrors.UNKNOWN_ENVIRONMENT`
|
||||
`debug` adds additional console logs to events
|
||||
|
||||
|
||||
## Errors
|
||||
Known errors could be one of following or an error throw by a callback specifically
|
||||
```ts
|
||||
enum RPCErrors {
|
||||
EVENT_NOT_REGISTERED = 'Event not registered',
|
||||
INVALID_DATA = 'Invalid data (possibly broken JSON)',
|
||||
NO_PLAYER = 'No player (failed to resolve from local index)',
|
||||
UNKNOWN_NATIVE = 'Unknown native event (if you are sure this exists - use native handler)',
|
||||
UNKNOWN_ENVIRONMENT = 'Unknown environment (must be either "server", "client" or "webview")',
|
||||
}
|
||||
```
|
||||
|
||||
### Example error
|
||||
Values wrapped in `<>` always exist, just not relevant for an example. Keep in mind that some errors are thrown in their destination(`To`) point: this example will throw on server
|
||||
```
|
||||
Error: No player (failed to resolve from local index)
|
||||
Event: 'clientServerEvent'
|
||||
Uuid: <uuid>
|
||||
From: 'client'
|
||||
To: 'server'
|
||||
Player: <non-existent-player>
|
||||
Type: 'event'
|
||||
Data: [<data>]
|
||||
```
|
||||
|
||||
## Server ([source](https://github.com/rilaxik/fivem-rpc/blob/master/rpc/src/core/server.ts))
|
||||
### onClient
|
||||
Listens to client event
|
||||
```ts
|
||||
rpc.onClient('clientServerEvent', (player, arg1, arg2, ...rest) => {
|
||||
// logic
|
||||
return someData // this will be forwarded back to caller
|
||||
})
|
||||
```
|
||||
### offClient
|
||||
Stops listening to client event
|
||||
```ts
|
||||
rpc.offClient('clientServerEvent')
|
||||
```
|
||||
### emitClient
|
||||
Sends event to specified client
|
||||
```ts
|
||||
const response = await rpc.emitClient(playerServerId, 'serverClientEvent', someData)
|
||||
// response will come from client listener with returned data
|
||||
```
|
||||
### emitClientEveryone
|
||||
Sends event to all clients
|
||||
```ts
|
||||
rpc.emitClientEveryone('serverClientEvent', someData)
|
||||
```
|
||||
### onWebview
|
||||
Listens to webview event
|
||||
```ts
|
||||
rpc.onWebview('webviewServerEvent', (player, arg1, arg2, ...rest) => {
|
||||
// logic
|
||||
return someData // this will be forwarded back to caller
|
||||
})
|
||||
```
|
||||
### offWebview
|
||||
Stops listening to webview event
|
||||
```ts
|
||||
rpc.offWebview('webviewServerEvent')
|
||||
```
|
||||
### emitWebview
|
||||
Sends event to specified webview
|
||||
```ts
|
||||
const response = await rpc.emitWebview(playerServerId, 'serverWebviewEvent', someData)
|
||||
// response will come from webview listener with returned data
|
||||
```
|
||||
### onSelf
|
||||
Listens to server event
|
||||
```ts
|
||||
rpc.onSelf('serverEvent', (arg1, arg2, ...rest) => {
|
||||
// logic
|
||||
return someData // this will be forwarded back to caller
|
||||
})
|
||||
```
|
||||
### offSelf
|
||||
Stops listening to server event
|
||||
```ts
|
||||
rpc.offSelf('serverEvent')
|
||||
```
|
||||
### emitSelf
|
||||
Sends event to server
|
||||
```ts
|
||||
const response = await rpc.emitSelf('serverEvent', someData)
|
||||
// response will come from server listener with returned data
|
||||
```
|
||||
### onCommand
|
||||
Registers chat command. Since arguments are untyped you must validate them yourself
|
||||
```ts
|
||||
rpc.onCommand('serverCommand', (player, args, commandRaw) => {
|
||||
// logic
|
||||
})
|
||||
```
|
||||
### onNativeEvent
|
||||
Listens to native server event ([reference](https://docs.fivem.net/docs/scripting-reference/events/server-events/))
|
||||
```ts
|
||||
rpc.onNativeEvent('playerJoining', (source, oldId) => {
|
||||
// logic
|
||||
})
|
||||
```
|
||||
|
||||
## Client ([source](https://github.com/rilaxik/fivem-rpc/blob/master/rpc/src/core/client.ts))
|
||||
### onServer
|
||||
Listens to server event
|
||||
```ts
|
||||
rpc.onServer('serverClientEvent', (arg1, arg2, ...rest) => {
|
||||
// logic
|
||||
return someData // this will be forwarded back to caller
|
||||
})
|
||||
```
|
||||
### offServer
|
||||
Stops listening to server event
|
||||
```ts
|
||||
rpc.offServer('serverClientEvent')
|
||||
```
|
||||
### emitServer
|
||||
Sends event to server
|
||||
```ts
|
||||
const response = await rpc.emitServer('clientServerEvent', someData)
|
||||
// response will come from webview listener with returned data
|
||||
```
|
||||
### onWebview
|
||||
Listens to webview event
|
||||
```ts
|
||||
rpc.onWebview('webviewClientEvent', (arg1, arg2, ...rest) => {
|
||||
// logic
|
||||
return someData // this will be forwarded back to caller
|
||||
})
|
||||
```
|
||||
### offWebview
|
||||
Stops listening to webview event
|
||||
```ts
|
||||
rpc.offWebview('webviewClientEvent')
|
||||
```
|
||||
### emitWebview
|
||||
Sends event to specified webview
|
||||
```ts
|
||||
const response = await rpc.emitWebview('clientWebviewEvent', someData)
|
||||
// response will come from webview listener with returned data
|
||||
```
|
||||
### onSelf
|
||||
Listens to client event
|
||||
```ts
|
||||
rpc.onSelf('clientEvent', (arg1, arg2, ...rest) => {
|
||||
// logic
|
||||
return someData // this will be forwarded back to caller
|
||||
})
|
||||
```
|
||||
### offSelf
|
||||
Stops listening to client event
|
||||
```ts
|
||||
rpc.offSelf('clientEvent')
|
||||
```
|
||||
### emitSelf
|
||||
Sends event to client
|
||||
```ts
|
||||
const response = await rpc.emitSelf('clientEvent', someData)
|
||||
// response will come from client listener with returned data
|
||||
```
|
||||
### onCommand
|
||||
Registers chat command. Since arguments are untyped you must validate them yourself
|
||||
```ts
|
||||
rpc.onCommand('clientCommand', (player, args, commandRaw) => {
|
||||
// logic
|
||||
})
|
||||
```
|
||||
### onNativeEvent
|
||||
Listens to native client event ([reference](https://docs.fivem.net/docs/scripting-reference/events/client-events/))
|
||||
```ts
|
||||
rpc.onNativeEvent('entityDamaged', (victim, culprit, weapon, baseDamage) => {
|
||||
// logic
|
||||
})
|
||||
```
|
||||
### onNativeNetworkEvent
|
||||
Listens to native client network event ([reference](https://docs.fivem.net/docs/game-references/game-events/))
|
||||
```ts
|
||||
rpc.onNativeNetworkEvent('CEventShockingCarCrash', (entities, eventEntity, data) => {
|
||||
// logic
|
||||
})
|
||||
```
|
||||
### setWebviewFocus
|
||||
Sets or removes focus and cursor from own webview
|
||||
```ts
|
||||
rpc.setWebviewFocus(true /* focus */, true /* show cursor */)
|
||||
```
|
||||
|
||||
## Webview ([source](https://github.com/rilaxik/fivem-rpc/blob/master/rpc/src/core/webview.ts))
|
||||
### onClient
|
||||
Listens to client event
|
||||
```ts
|
||||
rpc.onClient('clientWebviewEvent', (arg1, arg2, ...rest) => {
|
||||
// logic
|
||||
return someData // this will be forwarded back to caller
|
||||
})
|
||||
```
|
||||
### offClient
|
||||
Stops listening to client event
|
||||
```ts
|
||||
rpc.offClient('clientWebviewEvent')
|
||||
```
|
||||
### emitClient
|
||||
Sends event to own client
|
||||
```ts
|
||||
const response = await rpc.emitClient('webviewClientEvent', someData)
|
||||
// response will come from client listener with returned data
|
||||
```
|
||||
### onServer
|
||||
Listens to server event
|
||||
```ts
|
||||
rpc.onServer('serverWebviewEvent', (arg1, arg2, ...rest) => {
|
||||
// logic
|
||||
return someData // this will be forwarded back to caller
|
||||
})
|
||||
```
|
||||
### offServer
|
||||
Stops listening to server event
|
||||
```ts
|
||||
rpc.offServer('serverWebviewEvent')
|
||||
```
|
||||
### emitServer
|
||||
Sends event to server
|
||||
```ts
|
||||
const response = await rpc.emitServer('webviewServerEvent', someData)
|
||||
// response will come from webview listener with returned data
|
||||
```
|
||||
### onSelf
|
||||
Listens to webview event
|
||||
```ts
|
||||
rpc.onSelf('webviewEvent', (arg1, arg2, ...rest) => {
|
||||
// logic
|
||||
return someData // this will be forwarded back to caller
|
||||
})
|
||||
```
|
||||
### offSelf
|
||||
Stops listening to webview event
|
||||
```ts
|
||||
rpc.offSelf('webviewEvent')
|
||||
```
|
||||
### emitSelf
|
||||
Sends event to webview
|
||||
```ts
|
||||
const response = await rpc.emitSelf('webviewEvent', someData)
|
||||
// response will come from webview listener with returned data
|
||||
```
|
||||
|
||||
# License
|
||||
Licensed under Custom Attribution-NoDerivs Software License
|
||||
|
||||
@@ -64,9 +64,6 @@ class RPCFactory<T extends RPCEnvironment> extends Wrapper {
|
||||
}
|
||||
|
||||
export { RPCFactory }
|
||||
// export const rpcClient = new RPCFactory({ env: "client" }).get();
|
||||
// export const rpcServer = new RPCFactory({ env: "server" }).get();
|
||||
// export const rpcWebview = new RPCFactory({ env: "webview" }).get();
|
||||
export * from './utils/types'
|
||||
export * from './utils/native'
|
||||
export type * from './core/server'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@entityseven/fivem-rpc-shared-types",
|
||||
"description": "Shared types for @entityseven/fivem-rpc. Highly recommended to install together",
|
||||
"description": "Shared (enhanced) types for @entityseven/fivem-rpc. Highly recommended to install together",
|
||||
"version": "0.1.0",
|
||||
"types": "types/types/index.d.ts",
|
||||
"files": [
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
# FiveM RPC Shared Types
|
||||
### [Docs & Info](https://github.com/rilaxik/fivem-rpc/blob/master/readme.md)
|
||||
|
||||
## Installation
|
||||
```bash
|
||||
pnpm i @entityseven/fivem-rpc-shared-types -D
|
||||
```
|
||||
```bash
|
||||
yarn add @entityseven/fivem-rpc-shared-types --dev
|
||||
```
|
||||
```bash
|
||||
bun add @entityseven/fivem-rpc-shared-types -d
|
||||
```
|
||||
|
||||
## Usage
|
||||
This package is an enhanced type support for `@entityseven/fivem-rpc`. It provides ability to strictly type your events for better dx.
|
||||
|
||||
## Example
|
||||
This example is neat way to follow up but you can change it as you wish. It will use bun workspaces, pnpm workspaces work in a similar manner. Referring the following folder structure:
|
||||
```markdown
|
||||
apps/
|
||||
- server/
|
||||
- package.json
|
||||
- tsconfig.json
|
||||
- client/
|
||||
- package.json
|
||||
- tsconfig.json
|
||||
- webview/
|
||||
- package.json
|
||||
- tsconfig.json
|
||||
- shared/ (this must be available in server, client and webview)
|
||||
- package.json
|
||||
|
||||
- package.json (root package)
|
||||
- pnpm-workspace.yaml (only if using pnpm)
|
||||
```
|
||||
|
||||
- Environment folder: folder with server, client or webview code in it
|
||||
|
||||
1. Install this package as dev dependency in your root package or in each environment folder separately
|
||||
```markdown
|
||||
apps/
|
||||
- server/ <- (if not installed root)
|
||||
- client/ <- (if not installed root)
|
||||
- webview/ <- (if not installed root)
|
||||
- shared/
|
||||
|
||||
- package.json <- here
|
||||
```
|
||||
|
||||
2. In `shared/` create folder `fivem-rpc` (or similar), inside it create `index.d.ts`
|
||||
```markdown
|
||||
apps/
|
||||
- server/
|
||||
- client/
|
||||
- webview/
|
||||
- shared/
|
||||
- fivem-rpc/
|
||||
- index.d.ts <- here
|
||||
|
||||
- package.json
|
||||
```
|
||||
|
||||
3. In `index.d.ts` add following:
|
||||
```ts
|
||||
declare module '@entityseven/fivem-rpc-shared-types' {
|
||||
// Client commands names
|
||||
export type RPCCommands_Client = ''
|
||||
|
||||
// Server commands names
|
||||
export type RPCCommands_Server = ''
|
||||
|
||||
// Client -> Client events
|
||||
export interface RPCEvents_Client {}
|
||||
|
||||
// Client -> Server events
|
||||
export interface RPCEvents_ClientServer {}
|
||||
|
||||
// Client -> Webview events
|
||||
export interface RPCEvents_ClientWebview {}
|
||||
|
||||
// Server -> Server events
|
||||
export interface RPCEvents_Server {}
|
||||
|
||||
// Server -> Client events
|
||||
export interface RPCEvents_ServerClient {}
|
||||
|
||||
// Server -> Server events
|
||||
export interface RPCEvents_ServerWebview {}
|
||||
|
||||
// Webview -> Webview events
|
||||
export interface RPCEvents_Webview {}
|
||||
|
||||
// Webview -> Client events
|
||||
export interface RPCEvents_WebviewClient {}
|
||||
|
||||
// Webview -> Server events
|
||||
export interface RPCEvents_WebviewServer {}
|
||||
}
|
||||
```
|
||||
|
||||
4. We just created a declaration which will overwrite types from the package. Now we need our packages to refer to these types when linting `rpc` functions. To do this in each environment folder of your project in `tsconfig.json` do these:
|
||||
```json5
|
||||
{
|
||||
"compilerOptions": {
|
||||
"types": [
|
||||
"../shared/fivem-rpc/" // or your specific folder
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
5. We also need to populate interfaces we created in step 3.
|
||||
- `RPCCommands_Client` and `RPCCommands_Server` will include your commands names an union strings:
|
||||
```ts
|
||||
export type RPCCommands_Client = 'afk' | 'vanish' | '...' // example names
|
||||
export type RPCCommands_Server = 'report' | 'ban' | '...' // example names
|
||||
```
|
||||
- Other interfaces will include your events types. The example will show one but all of the work same way
|
||||
```ts
|
||||
export interface RPCEvents_ClientServer {
|
||||
clientToServerEventName(data: string, moreData: boolean): number
|
||||
"client-to-server-event-name"(data: string, moreData: boolean): number // can also include characters you cannot use as variable or function names
|
||||
}
|
||||
```
|
||||
- `clientToServerEventName` or `client-to-server-event-name` is an event name
|
||||
- `data` and `moreData` are the arguments you need to pass when calling an event and argument you will receive when listening (may also include extra, as player, check type hints)
|
||||
- `number` is a return type that will be forwarded back to caller
|
||||
|
||||
Doing this will create type hints for you:
|
||||
```ts
|
||||
// assuming this is in client
|
||||
const response /* number */ = await rpc.emitServer(
|
||||
'clientToServerEventName', /* suggested name */
|
||||
'data', /* will pass typecheck */
|
||||
'moreData', /* will NOT pass typecheck, since required type is `boolean` */
|
||||
)
|
||||
```
|
||||
|
||||
## Example (alternative)
|
||||
If previous example does not work or you do not like you can also try it this way. Steps that are not mentioned are the same as previous
|
||||
|
||||
2. In `shared/` create folders `declarations/fivem-rpc`, inside it create `index.d.ts`
|
||||
```markdown
|
||||
apps/
|
||||
- server/
|
||||
- client/
|
||||
- webview/
|
||||
- shared/
|
||||
- declarations/
|
||||
- fivem-rpc/
|
||||
- index.d.ts <- here
|
||||
|
||||
- package.json
|
||||
```
|
||||
|
||||
4. We just created a declaration which will overwrite types from the package. Now we need our packages to refer to these types when linting `rpc` functions. To do this in each environment folder of your project in `tsconfig.json` do these:
|
||||
```json5
|
||||
{
|
||||
"compilerOptions": {
|
||||
"typeRoots": [
|
||||
"../shared/declarations/", // or your specific folder
|
||||
"../../node_modules/@types", // you may also want to add this if some of your other libraries are not showing types now
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If a any point this stops working for you, do your research on how to redeclare library types and refer to it
|
||||
Reference in New Issue
Block a user