Compare commits
No commits in common. "987bba717ece09e3685dee4320bec994d0bb0f4e" and "1467bb65b0c8ff7024fd6fd7f070d3f362392576" have entirely different histories.
987bba717e
...
1467bb65b0
@ -1,6 +0,0 @@
|
|||||||
tabWidth: 4
|
|
||||||
printWidth: 80
|
|
||||||
singleQuote: true
|
|
||||||
semi: false
|
|
||||||
arrowParens: avoid
|
|
||||||
endOfLine: auto
|
|
@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "rpc",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"main": "dist/index.js",
|
|
||||||
"types": "dist/src/index.d.ts",
|
|
||||||
"scripts": {
|
|
||||||
"watch": "tsc -w",
|
|
||||||
"build": "tsup",
|
|
||||||
"start": "npx ./dist create"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"dist/**/*"
|
|
||||||
],
|
|
||||||
"description": "CLI to scaffold a template project for RageFW",
|
|
||||||
"keywords": [],
|
|
||||||
"author": "rilaxik",
|
|
||||||
"license": "ISC",
|
|
||||||
"devDependencies": {
|
|
||||||
"prettier": "^3.3.2",
|
|
||||||
"typescript": "^5.4.5"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
export const EVENT_LISTENER = '__rpc:listener'
|
|
||||||
export const EVENT_RESPONSE = '__rpc:response'
|
|
@ -1,61 +0,0 @@
|
|||||||
import { Environment, utils } from './utils'
|
|
||||||
import { EVENT_LISTENER } from './events'
|
|
||||||
|
|
||||||
import { client } from './modules/client'
|
|
||||||
import { server } from './modules/server'
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
public register<Callback extends any[] = unknown[], Return = unknown>(
|
|
||||||
eventName: string,
|
|
||||||
cb: (...args: Callback) => Return,
|
|
||||||
) {
|
|
||||||
if (environment === Environment.UNKNOWN) return
|
|
||||||
state[eventName] = cb
|
|
||||||
}
|
|
||||||
|
|
||||||
public async callClient<Args extends any[] = unknown[], Return = unknown>(
|
|
||||||
player: any,
|
|
||||||
eventName: string,
|
|
||||||
...args: Args
|
|
||||||
): Promise<Return | unknown> {
|
|
||||||
if (environment === Environment.UNKNOWN) return
|
|
||||||
if (environment === Environment.SERVER) {
|
|
||||||
return client.executeClient(player, eventName, args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async callServer<Args extends any[] = unknown[], Return = unknown>(
|
|
||||||
eventName: string,
|
|
||||||
...args: Args
|
|
||||||
): Promise<Return | unknown> {
|
|
||||||
if (environment === Environment.UNKNOWN) return
|
|
||||||
if (environment === Environment.CLIENT) {
|
|
||||||
return server.executeServer(eventName, args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const testRpc = new rpc()
|
|
||||||
export { testRpc }
|
|
@ -1,94 +0,0 @@
|
|||||||
import { EVENT_LISTENER } from '../events'
|
|
||||||
import { Wrapper } from './wrapper'
|
|
||||||
import { RPCState } from '../utils'
|
|
||||||
|
|
||||||
class Client extends Wrapper {
|
|
||||||
private sendResponseToServer(data: RPCState) {
|
|
||||||
const eventName = this._utils.generateResponseEventName(data.uuid)
|
|
||||||
const preparedData = this._utils.prepareForTransfer(data)
|
|
||||||
mp.events.callRemote(eventName, preparedData)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async listenEvent(data: string) {
|
|
||||||
const rpcData = this._verifyEvent(data)
|
|
||||||
|
|
||||||
if (rpcData.knownError) {
|
|
||||||
this._triggerError(rpcData)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const fnResponse = await this._state[rpcData.eventName](
|
|
||||||
...rpcData.data,
|
|
||||||
)
|
|
||||||
const response = {
|
|
||||||
...rpcData,
|
|
||||||
data: fnResponse,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sendResponseToServer(response)
|
|
||||||
} catch (e) {
|
|
||||||
this._triggerError(rpcData, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleClientServerReturn(
|
|
||||||
uuid: string,
|
|
||||||
resolve: (value: unknown) => void,
|
|
||||||
reject: (reason?: any) => void,
|
|
||||||
) {
|
|
||||||
const responseEvent = this._utils.generateResponseEventName(uuid)
|
|
||||||
const timeoutDuration = 1000 * 10
|
|
||||||
|
|
||||||
const timeoutID = setTimeout(() => {
|
|
||||||
reject(new Error('Timeout ended'))
|
|
||||||
mp.events.remove(responseEvent)
|
|
||||||
}, timeoutDuration)
|
|
||||||
|
|
||||||
const handler = (_: any, response: string) => {
|
|
||||||
const { knownError, data } = this._utils.prepareForExecute(response)
|
|
||||||
|
|
||||||
if (knownError)
|
|
||||||
try {
|
|
||||||
clearTimeout(timeoutID)
|
|
||||||
reject(knownError)
|
|
||||||
return
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
resolve(data)
|
|
||||||
mp.events.remove(responseEvent)
|
|
||||||
|
|
||||||
try {
|
|
||||||
clearTimeout(timeoutID)
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
mp.events.add(responseEvent, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async executeClient<
|
|
||||||
Args extends any[] = unknown[],
|
|
||||||
Return = unknown,
|
|
||||||
>(
|
|
||||||
player: any,
|
|
||||||
eventName: string,
|
|
||||||
...args: Args
|
|
||||||
): Promise<Return | unknown> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const uuid = this._utils.generateUUID()
|
|
||||||
|
|
||||||
const data: RPCState = {
|
|
||||||
uuid,
|
|
||||||
eventName,
|
|
||||||
calledFrom: this._environment,
|
|
||||||
data: args,
|
|
||||||
}
|
|
||||||
|
|
||||||
player.call(EVENT_LISTENER, [this._utils.prepareForTransfer(data)])
|
|
||||||
|
|
||||||
this.handleClientServerReturn(uuid, resolve, reject)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const client = new Client()
|
|
@ -1,95 +0,0 @@
|
|||||||
import { Wrapper } from './wrapper'
|
|
||||||
import { RPCState, utils } from '../utils'
|
|
||||||
import { EVENT_LISTENER } from '../events'
|
|
||||||
|
|
||||||
class Server extends Wrapper {
|
|
||||||
private sendResponseToClient(player: any, data: RPCState) {
|
|
||||||
const eventName = this._utils.generateResponseEventName(data.uuid)
|
|
||||||
const preparedData = this._utils.prepareForTransfer(data)
|
|
||||||
|
|
||||||
player.call(eventName, [preparedData])
|
|
||||||
}
|
|
||||||
|
|
||||||
public async listenEvent(player: any, data: string) {
|
|
||||||
const rpcData = this._verifyEvent(data)
|
|
||||||
|
|
||||||
if (rpcData.knownError) {
|
|
||||||
this._triggerError(rpcData)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const fnResponse = await this._state[rpcData.eventName](
|
|
||||||
...rpcData.data,
|
|
||||||
)
|
|
||||||
const response = {
|
|
||||||
...rpcData,
|
|
||||||
data: fnResponse,
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sendResponseToClient(player, response)
|
|
||||||
} catch (e) {
|
|
||||||
this._triggerError(rpcData, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleServerClientReturn(
|
|
||||||
uuid: string,
|
|
||||||
resolve: (value: unknown) => void,
|
|
||||||
reject: (reason?: any) => void,
|
|
||||||
) {
|
|
||||||
const responseEvent = this._utils.generateResponseEventName(uuid)
|
|
||||||
const timeoutDuration = 1000 * 10
|
|
||||||
|
|
||||||
const timeoutID = setTimeout(() => {
|
|
||||||
reject(new Error('Timeout ended'))
|
|
||||||
mp.events.remove(responseEvent)
|
|
||||||
}, timeoutDuration)
|
|
||||||
|
|
||||||
const handler = (response: string) => {
|
|
||||||
const { knownError, data } = this._utils.prepareForExecute(response)
|
|
||||||
|
|
||||||
if (knownError) {
|
|
||||||
try {
|
|
||||||
clearTimeout(timeoutID)
|
|
||||||
reject(knownError)
|
|
||||||
return
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(data)
|
|
||||||
mp.events.remove(responseEvent)
|
|
||||||
|
|
||||||
try {
|
|
||||||
clearTimeout(timeoutID)
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
mp.events.add(responseEvent, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
public async executeServer<
|
|
||||||
Args extends any[] = unknown[],
|
|
||||||
Return = unknown,
|
|
||||||
>(eventName: string, ...args: Args): Promise<Return | unknown> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const uuid = this._utils.generateUUID()
|
|
||||||
|
|
||||||
const data: RPCState = {
|
|
||||||
uuid,
|
|
||||||
eventName,
|
|
||||||
calledFrom: this._environment,
|
|
||||||
data: args,
|
|
||||||
}
|
|
||||||
|
|
||||||
mp.events.callRemote(
|
|
||||||
EVENT_LISTENER,
|
|
||||||
this._utils.prepareForTransfer(data),
|
|
||||||
)
|
|
||||||
|
|
||||||
this.handleServerClientReturn(uuid, resolve, reject)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const server = new Server()
|
|
@ -1,32 +0,0 @@
|
|||||||
import { Environment, Errors, RPCState, utils } from '../utils'
|
|
||||||
|
|
||||||
export class Wrapper {
|
|
||||||
public _utils = utils
|
|
||||||
public _environment = utils.getEnvironment()
|
|
||||||
public _state = this._environment === Environment.CEF ? window : global
|
|
||||||
|
|
||||||
public _verifyEvent(data: string): RPCState {
|
|
||||||
const rpcData = utils.prepareForExecute(data)
|
|
||||||
|
|
||||||
if (!this._state[rpcData.eventName]) {
|
|
||||||
rpcData.knownError = Errors.EVENT_NOT_REGISTERED
|
|
||||||
}
|
|
||||||
|
|
||||||
return rpcData
|
|
||||||
}
|
|
||||||
|
|
||||||
public _triggerError(rpcData: RPCState, error?: any) {
|
|
||||||
const errorMessage = [
|
|
||||||
`${rpcData.knownError}`,
|
|
||||||
`Caller: ${rpcData.calledFrom}`,
|
|
||||||
`Receiver: ${this._environment}`,
|
|
||||||
`Event: ${rpcData.eventName}`,
|
|
||||||
]
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
errorMessage.push(`Additional Info: ${error}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(errorMessage.join(' | '))
|
|
||||||
}
|
|
||||||
}
|
|
13
rpc/src/types.d.ts
vendored
13
rpc/src/types.d.ts
vendored
@ -1,13 +0,0 @@
|
|||||||
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: {
|
|
||||||
[p: string]: (...args: any[]) => unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
declare const window: {
|
|
||||||
[p: string]: (...args: any[]) => unknown
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es6",
|
|
||||||
"module": "commonjs",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"lib": ["ES6"],
|
|
||||||
"declaration": true,
|
|
||||||
"declarationMap": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
|
|
||||||
"outDir": "bin",
|
|
||||||
"esModuleInterop": true,
|
|
||||||
|
|
||||||
"strict": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"noImplicitAny": true
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/**/*"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import { defineConfig } from 'tsup'
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
entry: ['src/index.ts'],
|
|
||||||
outDir: './dist',
|
|
||||||
format: ['cjs'],
|
|
||||||
noExternal: ['rage-rpc'],
|
|
||||||
experimentalDts: true,
|
|
||||||
splitting: false,
|
|
||||||
sourcemap: false,
|
|
||||||
clean: true,
|
|
||||||
})
|
|
Loading…
Reference in New Issue
Block a user