Skip to content
This repository has been archived by the owner on Jun 5, 2024. It is now read-only.

Commit

Permalink
RPC Event System
Browse files Browse the repository at this point in the history
  • Loading branch information
Stuyk committed Apr 8, 2023
1 parent f9f448a commit 37fd189
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ Athena.systems.inventory.factory.getBaseItems
AthenaClient.systems.playerConfig.get('account-data') : Returns Filtered Account Data
AthenaClient.systems.playerConfig.get('character-data') : Returns Character Data
Athena.systems.rpc.invoke
AthenaClient.systems.rpc.on
--------------------------------------
--- Everything Below is Before April 2
--------------------------------------
Expand Down
1 change: 1 addition & 0 deletions src/core/client/systems/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export * as interaction from './interaction';
export * as inventory from './inventory';
export * as messenger from './messenger';
export * as playerConfig from './playerConfig';
export * as rpc from './rpc';
export * as sound from './sound';
export * as wheelMenu from '../views/wheelMenu';
25 changes: 25 additions & 0 deletions src/core/client/systems/rpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as alt from 'alt-client';

/**
* Handle an RPC event from server-side, and return a result back to the server.
*
* The RPC event must be invoked from server-side through the `Athena.systems.rpc.invoke` function.
*
* #### Example
* ```ts
* AthenaClient.systems.rpc.on('returnPlayerLocalPosition', () => {
* return alt.Player.local.pos;
* })
* ```
*
* @export
* @template T
* @param {string} eventName
* @param {(...args: any[]) => T} callback
*/
export function on<T = any>(eventName: string, callback: (...args: any[]) => T) {
alt.onServer(eventName, async (instancedName: string, ...args: any[]) => {
const result = await callback(...args);
alt.emitServer(instancedName, result);
});
}
1 change: 1 addition & 0 deletions src/core/server/systems/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export * as notification from '@AthenaServer/systems/notification';
export * as permission from '@AthenaServer/systems/permission';
export * as permissionGroup from '@AthenaServer/systems/permissionGroup';
export * as plugins from '@AthenaServer/systems/plugins';
export * as rpc from '@AthenaServer/systems/rpc';
export * as sound from '@AthenaServer/systems/sound';
export * as storage from '@AthenaServer/systems/storage';
export * as streamer from '@AthenaServer/systems/streamer';
Expand Down
100 changes: 100 additions & 0 deletions src/core/server/systems/rpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import * as alt from 'alt-server';
import * as Athena from '@AthenaServer/api';

export type Callback = (player: alt.Player, ...args: any[]) => void;

export interface ServerRpcEvent {
/**
* A general purpose name for the event.
*
* @type {string}
* @memberof ServerRpcEvent
*/
eventName: string;

/**
* Arguments to pass down to the client.
*
* @type {any[]}
* @memberof ServerRpcEvent
*/
args?: any[];

/**
* Kick, and log the user for not responding to an event.
*
* The value should be a message to send to the user.
*
* @type {string}
* @memberof ServerRpcEvent
*/
kickOnNoResponse?: string;

/**
* Timeout before the event is unregistered and removed.
*
* @type {number}
* @memberof ServerRpcEvent
*/
msTimeout: number;
}

/**
* Invoke an RPC event, and get a result.
*
* If the timeout expires; the callback will pass undefined.
*
* #### Example
* ```ts
* Athena.systems.rpc.invoke(somePlayer, 'getLocalPos', (player: alt.Player, pos: alt.IVector3) => {
* alt.log('RPC Position was' + JSON.stringify(pos));
* })
* ```
*
* @export
* @template T
* @param {alt.Player} player
* @param {ServerRpcEvent} event
* @param {(...T) => void} callback
* @return {*}
*/
export function invoke(player: alt.Player, event: ServerRpcEvent, callback: Callback) {
// Construct instanced event name
// Randomize it to help with collisions as well
const instancedName = Athena.utility.hash.sha256Random(`rpc:${player.id}:${event.eventName}`);

const callbackHandler = (player: alt.Player, ...args: any[]) => {
alt.clearTimeout(timeout);
callback(player, ...args);
};

const timeoutHandler = () => {
alt.offClient(instancedName, callbackHandler);
if (!event.kickOnNoResponse) {
return;
}

if (!player || !player.valid) {
return;
}

const data = Athena.document.character.get(player);
const mongoId = data && data._id ? data._id : 'Not Logged In';
alt.log(`${event.eventName} was called, but no response. ID: ${player.id} | MongoDB: ${mongoId}`);
player.kick(event.kickOnNoResponse);
};

// Clear old event if time is exceeded
const timeout = alt.setTimeout(timeoutHandler, event.msTimeout);

// Automatically unregisters itself once a client has pushed up the data
alt.onceClient(instancedName, callbackHandler);

// Call normal event name, and pass arguments down
if (event.args) {
player.emit(event.eventName, instancedName, ...event.args);
return;
}

player.emit(event.eventName, instancedName);
}
8 changes: 8 additions & 0 deletions src/core/shared/utility/rpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@


// server
// rpc.emit -> someEvent, someReturnValue

// client
// rpc.handle -> someEvent, pushToServer

0 comments on commit 37fd189

Please sign in to comment.