From de6dbae3a8e74840533067d2803932fedef2341e Mon Sep 17 00:00:00 2001 From: Danya H Date: Sun, 15 Sep 2024 21:55:08 +0100 Subject: [PATCH] upd | new rpc tests --- rpc/src-old/events.ts | 5 + rpc/src-old/index.ts | 76 ++++++++++++++++ rpc/{src => src-old}/modules/cef.ts | 0 rpc/{src => src-old}/modules/client.ts | 0 rpc/{src => src-old}/modules/server.ts | 0 rpc/{src => src-old}/modules/wrapper.ts | 0 rpc/{src => src-old}/types.d.ts | 0 rpc/src-old/utils.ts | 63 +++++++++++++ rpc/src/client.ts | 44 +++++++++ rpc/src/events.ts | 6 +- rpc/src/index.ts | 116 +++++++++++++++--------- rpc/src/server.ts | 33 +++++++ rpc/src/types.ts | 9 ++ rpc/src/utils.ts | 75 ++++++--------- rpc/tsconfig.json | 5 +- rpc/types.d.ts | 13 +++ 16 files changed, 347 insertions(+), 98 deletions(-) create mode 100644 rpc/src-old/events.ts create mode 100644 rpc/src-old/index.ts rename rpc/{src => src-old}/modules/cef.ts (100%) rename rpc/{src => src-old}/modules/client.ts (100%) rename rpc/{src => src-old}/modules/server.ts (100%) rename rpc/{src => src-old}/modules/wrapper.ts (100%) rename rpc/{src => src-old}/types.d.ts (100%) create mode 100644 rpc/src-old/utils.ts create mode 100644 rpc/src/client.ts create mode 100644 rpc/src/server.ts create mode 100644 rpc/src/types.ts create mode 100644 rpc/types.d.ts diff --git a/rpc/src-old/events.ts b/rpc/src-old/events.ts new file mode 100644 index 0000000..b3df93f --- /dev/null +++ b/rpc/src-old/events.ts @@ -0,0 +1,5 @@ +export const EVENT_LISTENER = '__rpc:listener' +export const EVENT_RESPONSE = '__rpc:response' +export const CEF_EVENT_LISTENER = '__rpc:cef_listener' + +export const CLIENT_ROUTER_LISTENER = '__rpc:clientRouter' diff --git a/rpc/src-old/index.ts b/rpc/src-old/index.ts new file mode 100644 index 0000000..8941b79 --- /dev/null +++ b/rpc/src-old/index.ts @@ -0,0 +1,76 @@ +import { Environment, utils } from './utils' +import { EVENT_LISTENER } from './events' + +import { client } from './modules/client' +import { server } from './modules/server' +import { cef } from './modules/cef' + +const environment = utils.getEnvironment() + +const state = environment === Environment.CEF ? window : global + +class rpc { + constructor() { + if (environment === Environment.UNKNOWN) return + + mp.events.add(EVENT_LISTENER, async (player: any, request: string) => { + switch (environment) { + case Environment.SERVER: + await server.listenEvent(player, request) + break + + case Environment.CLIENT: + request = player + + await client.listenEvent(request) + break + + case Environment.CEF: + request = player + + await cef + } + }) + } + + public register( + eventName: string, + cb: (...args: Callback) => Return, + ) { + if (environment === Environment.UNKNOWN) return + state[eventName] = cb + } + + public async callClient( + player: any, + eventName: string, + ...args: Args + ): Promise { + if (environment === Environment.UNKNOWN) return + if (environment === Environment.SERVER) { + return client.executeClient(player, eventName, args) + } + } + + public async callServer( + eventName: string, + ...args: Args + ): Promise { + switch (environment) { + case Environment.UNKNOWN: + return + + case Environment.SERVER: + return + + case Environment.CEF: + return client + + case Environment.CLIENT: + return server.executeServer(eventName, args) + } + } +} + +const testRpc = new rpc() +export { testRpc } diff --git a/rpc/src/modules/cef.ts b/rpc/src-old/modules/cef.ts similarity index 100% rename from rpc/src/modules/cef.ts rename to rpc/src-old/modules/cef.ts diff --git a/rpc/src/modules/client.ts b/rpc/src-old/modules/client.ts similarity index 100% rename from rpc/src/modules/client.ts rename to rpc/src-old/modules/client.ts diff --git a/rpc/src/modules/server.ts b/rpc/src-old/modules/server.ts similarity index 100% rename from rpc/src/modules/server.ts rename to rpc/src-old/modules/server.ts diff --git a/rpc/src/modules/wrapper.ts b/rpc/src-old/modules/wrapper.ts similarity index 100% rename from rpc/src/modules/wrapper.ts rename to rpc/src-old/modules/wrapper.ts diff --git a/rpc/src/types.d.ts b/rpc/src-old/types.d.ts similarity index 100% rename from rpc/src/types.d.ts rename to rpc/src-old/types.d.ts diff --git a/rpc/src-old/utils.ts b/rpc/src-old/utils.ts new file mode 100644 index 0000000..94ec71c --- /dev/null +++ b/rpc/src-old/utils.ts @@ -0,0 +1,63 @@ +import { EVENT_RESPONSE } from './events' + +export enum Environment { + CEF = 'CEF', + CLIENT = 'CLIENT', + SERVER = 'SERVER', + UNKNOWN = 'UNKNOWN', +} + +export enum Errors { + EVENT_NOT_REGISTERED = 'Event not registered', +} + +export type RPCState = { + eventName: string + uuid: string + knownError?: string + data?: any + calledFrom: Environment + calledTo: Environment +} + +class Utils { + public getEnvironment(): Environment { + if (mp.joaat) return Environment.SERVER + if (mp.game && mp.game.joaat) return Environment.CLIENT + if ('mp' in window) return Environment.CEF + return Environment.UNKNOWN + } + + public prepareForExecute(data: string): RPCState { + return JSON.parse(data) + } + + public prepareForTransfer(data: RPCState): string { + return JSON.stringify(data) + } + + public generateUUID(): string { + let uuid = '', + random + + for (let i = 0; i < 32; i++) { + random = (Math.random() * 16) | 0 + + if (i === 8 || i === 12 || i === 16 || i === 20) { + uuid += '-' + } + + uuid += ( + i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random + ).toString(16) + } + + return uuid + } + + public generateResponseEventName(uuid: string): string { + return `${EVENT_RESPONSE}_${uuid}` + } +} + +export const utils = new Utils() diff --git a/rpc/src/client.ts b/rpc/src/client.ts new file mode 100644 index 0000000..1a5dc2e --- /dev/null +++ b/rpc/src/client.ts @@ -0,0 +1,44 @@ +import { utils } from './utils' +import type { RPCData } from './types' + +export class Client { + public async listen(data: string) { + const parsedData = utils.parseData(data) + await this.transferTo(parsedData) + } + + private transferTo(data: RPCData) { + switch (data.to) { + case utils.environment.CLIENT: + return this.executeLocal(data) + case utils.environment.CEF: + // todo transfer to cef + case utils.environment.SERVER: + // todo transfer to server + } + } + + private async executeLocal(data: RPCData) { + const state = + utils.getEnvironment() === utils.environment.CEF + ? window.rpcEvents + : global.rpcEvents + const fnResponse = await state[data.eventName](...data.data) + + const response = { + data: fnResponse, + ...data, + } + + this.sendResponseToServer(response) + } + + private sendResponseToServer(data: RPCData) { + const eventName = utils.generateResponseEventName(data.uuid) + const prepareForTransfer = utils.stringifyData(data) + + mp.events.callRemote(eventName, prepareForTransfer) + } +} + +export const client = new Client() diff --git a/rpc/src/events.ts b/rpc/src/events.ts index b3df93f..94e59ef 100644 --- a/rpc/src/events.ts +++ b/rpc/src/events.ts @@ -1,5 +1,3 @@ -export const EVENT_LISTENER = '__rpc:listener' -export const EVENT_RESPONSE = '__rpc:response' -export const CEF_EVENT_LISTENER = '__rpc:cef_listener' +export const RPC_LISTENER = 'rpc::listener' -export const CLIENT_ROUTER_LISTENER = '__rpc:clientRouter' +export const CLIENT_ROUTER_LISTENER = 'rpc::clientRouterListener' \ No newline at end of file diff --git a/rpc/src/index.ts b/rpc/src/index.ts index 8941b79..6dab4d9 100644 --- a/rpc/src/index.ts +++ b/rpc/src/index.ts @@ -1,76 +1,104 @@ +import { RPC_LISTENER } from './events' import { Environment, utils } from './utils' -import { EVENT_LISTENER } from './events' -import { client } from './modules/client' -import { server } from './modules/server' -import { cef } from './modules/cef' +import { client } from './client' +import { server } from './server' +import type { RPCData } from './types.ts' -const environment = utils.getEnvironment() +class FrameworkRpc { + private readonly _environment: Environment + private readonly _environmentGlobal: Record -const state = environment === Environment.CEF ? window : global - -class rpc { constructor() { - if (environment === Environment.UNKNOWN) return + this._environment = utils.getEnvironment() + this._environmentGlobal = + utils.getEnvironment() === utils.environment.CEF + ? window.rpcEvents + : global.rpcEvents - mp.events.add(EVENT_LISTENER, async (player: any, request: string) => { - switch (environment) { - case Environment.SERVER: - await server.listenEvent(player, request) - break + mp.events.add(RPC_LISTENER, async (player: any, data: string) => { + switch (this._environment) { + case utils.environment.UNKNOWN: + return - case Environment.CLIENT: - request = player + case utils.environment.CLIENT: + player = data + return client.listen(player) - await client.listenEvent(request) - break + case utils.environment.SERVER: + return server.listen(player, data) - case Environment.CEF: - request = player - - await cef + case utils.environment.CEF: } }) } - public register( + public register( eventName: string, - cb: (...args: Callback) => Return, + cb: (...args: Args) => Return, ) { - if (environment === Environment.UNKNOWN) return - state[eventName] = cb + if (this._environment === utils.environment.UNKNOWN) return + this._environmentGlobal[eventName] = cb } - public async callClient( + public callClient( player: any, eventName: string, ...args: Args ): Promise { - if (environment === Environment.UNKNOWN) return - if (environment === Environment.SERVER) { - return client.executeClient(player, eventName, args) - } + return new Promise((resolve, _reject) => { + const uuid = utils.generateUUID() + + const data: RPCData = { + uuid, + eventName, + from: this._environment, + to: utils.environment.CLIENT, + data: args, + } + + player.call(RPC_LISTENER, [utils.stringifyData(data)]) + + const responseEventName = utils.generateResponseEventName(uuid) + + const handler = (_player: any, data: string) => { + resolve(utils.parseData(data).data) + mp.events.remove(responseEventName) + } + + mp.events.add(responseEventName, handler) + }) } - public async callServer( + public callServer( eventName: string, ...args: Args ): Promise { - switch (environment) { - case Environment.UNKNOWN: - return + return new Promise((resolve, _reject) => { + const uuid = utils.generateUUID() - case Environment.SERVER: - return + const data: RPCData = { + uuid, + eventName, + from: this._environment, + to: utils.environment.CLIENT, + data: args, + } - case Environment.CEF: - return client + mp.events.callRemote(RPC_LISTENER, utils.stringifyData(data)) - case Environment.CLIENT: - return server.executeServer(eventName, args) - } + const responseEventName = utils.generateResponseEventName(uuid) + + const handler = (_player: any, data: string) => { + resolve(utils.parseData(data).data) + mp.events.remove(responseEventName) + } + + mp.events.add(responseEventName, handler) + }) } } -const testRpc = new rpc() -export { testRpc } +const rpc = new FrameworkRpc() + +export { rpc } diff --git a/rpc/src/server.ts b/rpc/src/server.ts new file mode 100644 index 0000000..0202cc0 --- /dev/null +++ b/rpc/src/server.ts @@ -0,0 +1,33 @@ +import { utils } from './utils' +import type { RPCData } from './types' + +export class Server { + public async listen(player: any, data: string) { + const parsedData = utils.parseData(data) + await this.executeLocal(player, parsedData) + } + + private async executeLocal(player: any, data: RPCData) { + const state = + utils.getEnvironment() === utils.environment.CEF + ? window.rpcEvents + : global.rpcEvents + const fnResponse = await state[data.eventName](...data.data) + + const response = { + data: fnResponse, + ...data, + } + + this.sendResponseToClient(player, response) + } + + private sendResponseToClient(player: any, data: RPCData) { + const eventName = utils.generateResponseEventName(data.uuid) + const prepareForTransfer = utils.stringifyData(data) + + player.call(eventName, prepareForTransfer) + } +} + +export const server = new Server() diff --git a/rpc/src/types.ts b/rpc/src/types.ts new file mode 100644 index 0000000..dd62519 --- /dev/null +++ b/rpc/src/types.ts @@ -0,0 +1,9 @@ +import { Environment } from './utils' + +export type RPCData = { + data?: any + from: Environment + to: Environment + eventName: string + uuid: string +} diff --git a/rpc/src/utils.ts b/rpc/src/utils.ts index 94ec71c..ce06975 100644 --- a/rpc/src/utils.ts +++ b/rpc/src/utils.ts @@ -1,4 +1,5 @@ -import { EVENT_RESPONSE } from './events' +import type { RPCData } from './types' +import { RPC_LISTENER } from './events' export enum Environment { CEF = 'CEF', @@ -7,57 +8,35 @@ export enum Environment { UNKNOWN = 'UNKNOWN', } -export enum Errors { - EVENT_NOT_REGISTERED = 'Event not registered', +function generateUUID(): string { + let uuid = '', + random + + for (let i = 0; i < 32; i++) { + random = (Math.random() * 16) | 0 + + if (i === 8 || i === 12 || i === 16 || i === 20) { + uuid += '-' + } + + uuid += (i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random).toString( + 16, + ) + } + + return uuid } -export type RPCState = { - eventName: string - uuid: string - knownError?: string - data?: any - calledFrom: Environment - calledTo: Environment -} - -class Utils { - public getEnvironment(): Environment { +export const utils = { + environment: Environment, + getEnvironment: () => { if (mp.joaat) return Environment.SERVER if (mp.game && mp.game.joaat) return Environment.CLIENT if ('mp' in window) return Environment.CEF return Environment.UNKNOWN - } - - public prepareForExecute(data: string): RPCState { - return JSON.parse(data) - } - - public prepareForTransfer(data: RPCState): string { - return JSON.stringify(data) - } - - public generateUUID(): string { - let uuid = '', - random - - for (let i = 0; i < 32; i++) { - random = (Math.random() * 16) | 0 - - if (i === 8 || i === 12 || i === 16 || i === 20) { - uuid += '-' - } - - uuid += ( - i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random - ).toString(16) - } - - return uuid - } - - public generateResponseEventName(uuid: string): string { - return `${EVENT_RESPONSE}_${uuid}` - } + }, + parseData: (data: string): RPCData => JSON.parse(data), + stringifyData: (data: RPCData): string => JSON.stringify(data), + generateResponseEventName: (uuid: string) => `${RPC_LISTENER}_${uuid}`, + generateUUID, } - -export const utils = new Utils() diff --git a/rpc/tsconfig.json b/rpc/tsconfig.json index f8996ab..236145d 100644 --- a/rpc/tsconfig.json +++ b/rpc/tsconfig.json @@ -13,10 +13,11 @@ "strict": true, "forceConsistentCasingInFileNames": true, - "noImplicitAny": true + "noImplicitAny": true, }, "include": [ - "src/**/*" + "src/**/*", + "./types.d.ts" ], "exclude": [ "node_modules" diff --git a/rpc/types.d.ts b/rpc/types.d.ts new file mode 100644 index 0000000..f230e07 --- /dev/null +++ b/rpc/types.d.ts @@ -0,0 +1,13 @@ +declare const mp: any +declare const console: any + +declare const setTimeout: (fn: Function, time: number) => number +declare const clearTimeout: (id: number) => void + +declare const global: { + rpcEvents: Record unknown> +} + +declare const window: { + rpcEvents: Record unknown> +}