diff --git a/.gitignore b/.gitignore index 68d94e9..ff08c6c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ server/ragemp-server.exe # Development node_modules -pnpm-lock.yaml \ No newline at end of file +pnpm-lock.yaml +dist \ No newline at end of file diff --git a/apps/cef/src/App.tsx b/apps/cef/src/App.tsx index 8d962b7..c95e5af 100644 --- a/apps/cef/src/App.tsx +++ b/apps/cef/src/App.tsx @@ -1,20 +1,18 @@ -import { fw } from 'rage-fw-cef' import { useEffect, useState } from 'react' +import { rpc } from 'rpc' function App() { - const [data, setData] = useState('') + const [data, setData] = useState('') useEffect(() => { - fw.event.register('customCefEvent', async ([test]) => { - setData(p => p + ' ' + test) - return 'from cef' - }) + rpc.callClient('cefReady', []) + rpc.register('customCefEvent', args => setData(args)) }, []) return (

Hello World!

-

{data}

+

{data!.toString()}

) } diff --git a/apps/client/src/index.ts b/apps/client/src/index.ts index bc23c27..24dbb34 100644 --- a/apps/client/src/index.ts +++ b/apps/client/src/index.ts @@ -1,14 +1,15 @@ -import { fw } from 'rage-fw-client' +import { rpc, client } from 'rpc' -fw.player.browser = mp.browsers.new('package://cef/index.html') +client.browser = mp.browsers.new('package://cef/index.html') -fw.event.register('cefReady', async () => { - fw.system.log.info('cefReady') +rpc.register('cefReady', async () => { + mp.console.logInfo('cef to client') - const responseCef = await fw.player.triggerBrowser('customCefEvent', [ - 'from client', - ]) - fw.system.log.info(responseCef) - - await fw.player.triggerServer('customServerEvent', ['from client']) + rpc.callServer('customServerEvent', ['client to server']) +}) + +rpc.register('customClientEvent', async data => { + mp.console.logInfo(JSON.stringify(data)) + + rpc.callBrowser('customCefEvent', ['client to cef']) }) diff --git a/apps/rpc/index.d.ts b/apps/rpc/index.d.ts index 5991e99..3ac3864 100644 --- a/apps/rpc/index.d.ts +++ b/apps/rpc/index.d.ts @@ -1,9 +1,8 @@ -declare const mp: any +import '@ragempcommunity/types-cef' +import '@ragempcommunity/types-client' +import '@ragempcommunity/types-server' -declare const global: { - rpcEvents: Record unknown> -} - -declare const window: { - rpcEvents: Record unknown> -} +declare const mp: Mp +declare const global: Record unknown> +declare const window: Record unknown> +declare const console: { log: (...args: any[]) => void } diff --git a/apps/rpc/package.json b/apps/rpc/package.json index b0a239d..55859b4 100644 --- a/apps/rpc/package.json +++ b/apps/rpc/package.json @@ -1,7 +1,7 @@ { "name": "rpc", "version": "0.1.0", - "main": "dist/index.js", + "main": "src/index.ts", "types": "dist/src/index.d.ts", "scripts": { "build": "tsup", @@ -11,7 +11,12 @@ "dist/**/*" ], "devDependencies": { - "prettier": "^3.3.2" + "@microsoft/api-extractor": "^7.47.9", + "@ragempcommunity/types-client": "^2.1.8", + "@ragempcommunity/types-server": "^2.1.8", + "@ragempcommunity/types-cef": "^2.1.8", + "prettier": "^3.3.2", + "tsup": "^8.3.0" }, "peerDependencies": { "typescript": "^5.0.0" @@ -19,10 +24,12 @@ "description": "RageFW RPC", "keywords": [], "author": "SashaGoncharov19", - "contributors": [{ - "name": "rilaxik", - "email": "dev.rilaxik@gmail.com", - "url": "https://github.com/rilaxik" - }], + "contributors": [ + { + "name": "rilaxik", + "email": "dev.rilaxik@gmail.com", + "url": "https://github.com/rilaxik" + } + ], "license": "MIT" } diff --git a/apps/rpc/src/browser.ts b/apps/rpc/src/browser.ts index 994d93e..7404729 100644 --- a/apps/rpc/src/browser.ts +++ b/apps/rpc/src/browser.ts @@ -23,7 +23,7 @@ class Browser extends Wrapper { } private emitClient(dataRaw: string) { - mp.trigger(Events.EVENT_LISTENER, dataRaw) + mp.trigger(Events.LOCAL_EVENT_LISTENER, dataRaw) } private emit(dataRaw: string) { diff --git a/apps/rpc/src/client.ts b/apps/rpc/src/client.ts index 314ac73..7299f0a 100644 --- a/apps/rpc/src/client.ts +++ b/apps/rpc/src/client.ts @@ -44,11 +44,13 @@ class Client extends Wrapper { return } - this.state_[state.eventName](...state.data) + this.state_[state.eventName]( + ...(Array.isArray(state.data) ? state.data : []), + ) } private emitServer(dataRaw: string) { - mp.events.callRemote(Events.EVENT_LISTENER, dataRaw) + mp.events.callRemote(Events.SERVER_EVENT_LISTENER, dataRaw) } private emitBrowser(dataRaw: string, state: RPCState) { @@ -57,7 +59,7 @@ class Client extends Wrapper { return } - this._browser.call(Events.EVENT_LISTENER, dataRaw) + this._browser.call(Events.LOCAL_EVENT_LISTENER, dataRaw) } } diff --git a/apps/rpc/src/index.ts b/apps/rpc/src/index.ts index 9534107..de2dbe0 100644 --- a/apps/rpc/src/index.ts +++ b/apps/rpc/src/index.ts @@ -1,9 +1,15 @@ import { Wrapper } from './wrapper' +import type { Player, PlayerServer } from './utils' import { Environment, Errors, Events, RPCState, Utils } from './utils' + import { server } from './server' import { client } from './client' import { browser } from './browser' +export { server } from './server' +export { client } from './client' +export { browser } from './browser' + class Rpc extends Wrapper { constructor() { super() @@ -12,22 +18,20 @@ class Rpc extends Wrapper { throw new Error(Errors.UNKNOWN_ENVIRONMENT) mp.events.add( - Events.EVENT_LISTENER, - async (player: any, dataRaw: string) => { - if (!dataRaw) throw new Error(Errors.NO_DATA) - + Events.LOCAL_EVENT_LISTENER, + async (player: Player, dataRaw: string) => { switch (this.environment_) { case Environment.SERVER: server.resolveEmitDestination(player, dataRaw) break case Environment.CLIENT: - dataRaw = player + dataRaw = player as string client.resolveEmitDestination(dataRaw) break case Environment.BROWSER: - dataRaw = player + dataRaw = player as string browser.resolveEmitDestination(dataRaw) break @@ -48,29 +52,61 @@ class Rpc extends Wrapper { this.state_[eventName] = cb } - public unregister( - eventName: string - ): void { + public unregister(eventName: string): void { Utils.errorUnknownEnvironment(this.environment_) delete this.state_[eventName] } - public callClient(eventName: string, args: unknown[]) { + public callClient( + playerOrEventName: Player, + eventNameOrArgs: string | unknown[], + args?: unknown[], + ) { Utils.errorUnknownEnvironment(this.environment_) - const state: RPCState = { - uuid: Utils.generateUUID(), - eventName, - calledTo: Environment.CLIENT, - calledFrom: this.environment_, - knownError: undefined, - data: args, + // client + if (this.environment_ === Environment.CLIENT) { + this.call(playerOrEventName as string, args as unknown[]) + return } - const dataRaw = Utils.prepareTransfer(state) + // server + if (this.environment_ === Environment.SERVER) { + const state: RPCState = { + uuid: Utils.generateUUID(), + eventName: eventNameOrArgs as string, + calledTo: Environment.CLIENT, + calledFrom: this.environment_, + knownError: undefined, + data: args as unknown[], + } - mp.events.call(Events.EVENT_LISTENER, dataRaw) + const dataRaw = Utils.prepareTransfer(state) + + ;(playerOrEventName as PlayerServer).call( + Events.LOCAL_EVENT_LISTENER, + [dataRaw], + ) + return + } + + // browser + if (this.environment_ === Environment.BROWSER) { + const state: RPCState = { + uuid: Utils.generateUUID(), + eventName: playerOrEventName as string, + calledTo: Environment.CLIENT, + calledFrom: this.environment_, + knownError: undefined, + data: eventNameOrArgs as unknown[], + } + + const dataRaw = Utils.prepareTransfer(state) + + mp.trigger(Events.LOCAL_EVENT_LISTENER, dataRaw) + return + } } public callServer(eventName: string, args: unknown[]) { @@ -85,9 +121,13 @@ class Rpc extends Wrapper { data: args, } - const dataRaw = Utils.prepareTransfer(state) + if (state.calledFrom === Environment.SERVER) { + this.callSelf(state) + } else { + const dataRaw = Utils.prepareTransfer(state) - mp.events.call(Events.EVENT_LISTENER, dataRaw) + mp.events.call(Events.LOCAL_EVENT_LISTENER, dataRaw) + } } public callBrowser(eventName: string, args: unknown[]) { @@ -102,9 +142,13 @@ class Rpc extends Wrapper { data: args, } - const dataRaw = Utils.prepareTransfer(state) + if (state.calledFrom === Environment.BROWSER) { + this.callSelf(state) + } else { + const dataRaw = Utils.prepareTransfer(state) - mp.events.call(Events.EVENT_LISTENER, dataRaw) + mp.events.call(Events.LOCAL_EVENT_LISTENER, dataRaw) + } } public call(eventName: string, args: unknown[]) { @@ -119,11 +163,17 @@ class Rpc extends Wrapper { data: args, } + this.callSelf(state) + } + + private callSelf(state: RPCState) { state = this.verifyEvent_(state) if (state.knownError) { this.triggerError_(state, state.knownError) return } + + this.state_[state.eventName](...state.data) } } diff --git a/apps/rpc/src/server.ts b/apps/rpc/src/server.ts index bf747d2..58a4b3f 100644 --- a/apps/rpc/src/server.ts +++ b/apps/rpc/src/server.ts @@ -1,14 +1,20 @@ import { Wrapper } from './wrapper' -import { Environment, Errors, Events, Utils } from './utils' +import type { Player, PlayerServer } from './utils' +import { Environment, Events, Utils } from './utils' class Server extends Wrapper { constructor() { super() + + mp.events.add( + Events.SERVER_EVENT_LISTENER, + async (player: PlayerServer, dataRaw: string) => { + this.emit(player, dataRaw) + }, + ) } - public resolveEmitDestination(player: any, dataRaw: string) { - if (!dataRaw) throw new Error(Errors.NO_DATA) - + public resolveEmitDestination(player: Player, dataRaw: string) { let state = Utils.prepareExecution(dataRaw) switch (state.calledTo) { @@ -17,16 +23,16 @@ class Server extends Wrapper { break default: - this.emitClient(player, dataRaw) + this.emitClient(player as PlayerServer, dataRaw) break } } - private emitClient(player: any, dataRaw: string) { - player.call(Events.EVENT_LISTENER, dataRaw) + private emitClient(player: PlayerServer, dataRaw: string) { + player.call(Events.LOCAL_EVENT_LISTENER, [dataRaw]) } - private emit(player: any, dataRaw: string) { + private emit(player: Player, dataRaw: string) { let state = Utils.prepareExecution(dataRaw) state = this.verifyEvent_(state) @@ -36,7 +42,7 @@ class Server extends Wrapper { } const { eventName, data } = Utils.prepareExecution(dataRaw) - this.state_[eventName](...data) + this.state_[eventName](player, ...data) } } diff --git a/apps/rpc/src/utils.ts b/apps/rpc/src/utils.ts index a350c5f..fffb575 100644 --- a/apps/rpc/src/utils.ts +++ b/apps/rpc/src/utils.ts @@ -6,7 +6,9 @@ export enum Environment { } export enum Events { - EVENT_LISTENER = '__rpc:listener', + LOCAL_EVENT_LISTENER = '__rpc:listener', + CLIENT_EVENT_LISTENER = '__rpc:clientListener', + SERVER_EVENT_LISTENER = '__rpc:serverListener', EVENT_RESPONSE = '__rpc:response', } @@ -17,15 +19,6 @@ export enum Errors { NO_BROWSER = 'You need to initialize browser first', } -export type RPCState = { - eventName: string - uuid: string - knownError?: string - data?: any - calledFrom: Environment - calledTo: Environment -} - export class Utils { public static getEnvironment(): Environment { if ('joaat' in mp) return Environment.SERVER @@ -71,3 +64,17 @@ export class Utils { throw new Error(Errors.UNKNOWN_ENVIRONMENT) } } + +export type RPCState = { + eventName: string + uuid: string + knownError?: string + data?: any + calledFrom: Environment + calledTo: Environment +} + +export interface Player {} +export interface PlayerServer extends Player { + call(eventName: string, args: unknown[]): void +} diff --git a/apps/rpc/src/wrapper.ts b/apps/rpc/src/wrapper.ts index f3e054a..b5d75cf 100644 --- a/apps/rpc/src/wrapper.ts +++ b/apps/rpc/src/wrapper.ts @@ -3,15 +3,7 @@ import { Environment, Errors, RPCState, Utils } from './utils' export class Wrapper { protected environment_ = Utils.getEnvironment() protected state_ = - this.environment_ === Environment.BROWSER - ? (window.rpcEvents = {} as Record< - string, - (...args: any[]) => unknown - >) - : (global.rpcEvents = {} as Record< - string, - (...args: any[]) => unknown - >) + this.environment_ === Environment.BROWSER ? window : global protected verifyEvent_(data: string | RPCState): RPCState { let rpcData = diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index 63e964c..5a3870e 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -1,18 +1,11 @@ -import { fw } from 'rage-fw-server' +import { rpc } from 'rpc' -fw.event.register('playerJoin', async ([player]) => { - fw.system.log.info(`Connected: ${player.socialClub}`) +rpc.register('playerJoin', async player => { + console.log(`Connected: ${player.socialClub}`) }) -fw.event.register('customServerEvent', async ([player, msg]) => { - fw.system.log.info(player.socialClub + ' ' + msg) +rpc.register('customServerEvent', (player, data) => { + console.log(player, data) - const resFromCef = await fw.player.triggerBrowser( - player, - 'customCefEvent', - ['from server'], - ) - fw.system.log.info(player.socialClub + ' ' + resFromCef) - - return 'from server' + rpc.callClient(player, 'customClientEvent', ['server to client']) }) diff --git a/apps/server/tsconfig.json b/apps/server/tsconfig.json index 7f70b26..5064ffe 100644 --- a/apps/server/tsconfig.json +++ b/apps/server/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "../../tsconfig.json", "compilerOptions": { + "lib": ["DOM", "ESNext"], "resolveJsonModule": true, "baseUrl": "./src", "types": [ diff --git a/apps/shared/declarations/rage-fw-shared-types/index.d.ts b/apps/shared/declarations/rage-fw-shared-types/index.d.ts index 5156884..a5e414e 100644 --- a/apps/shared/declarations/rage-fw-shared-types/index.d.ts +++ b/apps/shared/declarations/rage-fw-shared-types/index.d.ts @@ -1,11 +1,13 @@ declare module 'rage-fw-shared-types' { - export interface RageFW_ICustomClientEvent {} + export interface RageFW_ICustomClientEvent { + customClientEvent(greetings: string): void + } export interface RageFW_ICustomServerEvent { - customServerEvent(greetings: string): string + customServerEvent(greetings: string): void } export interface RageFW_ICustomCefEvent { - customCefEvent(greetings: string): string + customCefEvent(greetings: string): void } }