micaww 32 Posted March 6 Version 0.2.0 has been released. This update has a few new convenience features as well as a bug fix. The bug, found by @Yiin , made CEF fail when retrieving an inbound event with a single quote in it. For example an error message with an apostrophe. This has been solved and the fix is included in the latest release. As for features, 2 things were added: 1. Send any number of multiplayer objects between server and client. Previously, to access a multiplayer object remotely, you had to send the ID or remote ID of it and then get the entity by that ID on the other side. This is no more! You can now embed any synced multiplayer object right into your arguments, or return them from any of your procedures without extra work. They don't have to be the only argument either. You can put multiplayer objects at any level within your argument object/array. This currently doesn't work for events that communicate with the browser. I may add some kind of way to interface multiplayer objects directly from the browser in the future. Here are some examples: /* Allow clients to ask for the server to delete some vehicles */ // Client-side const veh1 = mp.vehicles.at(0); const veh2 = mp.players.local.vehicle; rpc.callServer('deleteVehicles', [veh1, veh2]); // Server-side rpc.register('deleteVehicles', vehicles => { vehicles.forEach(veh => veh.destroy()); }); /* Get information on a certain vehicle, including the players currently in it (whether they're currently streamed in or not) */ // Client-side const veh = mp.vehicles.atRemoteId(6); rpc.callServer('getVehicleInfo', veh).then(data => { // let's print the names of all players in this vehicle mp.game.graphics.notify('~g~' + data.occupants.map(ply => ply.name).join(', ')); }); // Server-side rpc.register('getVehicleInfo', veh => ({ bodyHealth: veh.bodyHealth, plate: veh.numberPlate occupants: veh.getOccupants() // an array of Players in the vehicle })); 2. Add "browser" property to client callback info when a procedure is called from CEF. One thing about native events using mp.trigger is that there is no way to easily tell which browser triggered the event. Now, in client-side register, you can see the browser instance that called the event because it is passed into the caller info. This of course allows you to further manipulate the browser by executing more code, destroying it, etc. For example, you may want to give browsers the ability to close themselves without creating a separate event for each browser instance: // Client-side rpc.register('closeBrowser', (_, { browser }) => { // `browser` is the RAGE:MP Browser instance that called this event browser.destroy(); }); // Any CEF browser rpc.callClient('closeBrowser'); Simple as that. I hope you all find these additions useful! 2 Share this post Link to post Share on other sites
buxx0 2 Posted March 31 Beast package. The only thing is I can't use it with es6 import but it's not important. Good job🔥 Share this post Link to post Share on other sites
micaww 32 Posted April 1 @buxx0 The module is UMD so you can use it with es6 import! I do in my code aswell. Like so: import * as rpc from 'rage-rpc'; It just doesn't have a default export, so you have to wildcard it. 1 Share this post Link to post Share on other sites
micaww 32 Posted April 3 @buxx0 thanks to @Yiin default export will be available in next release: https://github.com/micaww/rage-rpc/pull/7 You can build yourself on git if you'd like it now! More features incoming if not. Share this post Link to post Share on other sites
OLTEANUadv 1 Posted May 23 (edited) How to install it on clientside? Edited May 23 by OLTEANUadv Share this post Link to post Share on other sites
Shooter 1 Posted May 23 vor 2 Stunden schrieb OLTEANUadv: How to install it on clientside? Hey... you have to integrate the require command correctly in the index.js ... is there an index.js in your folder rage-rpc? 1 Share this post Link to post Share on other sites
OLTEANUadv 1 Posted May 24 9 hours ago, Shooter said: Hey... you have to integrate the require command correctly in the index.js ... is there an index.js in your folder rage-rpc? Fixed, thx! Share this post Link to post Share on other sites
HankSteiner 7 Posted May 30 Hey I just discovered rpc and want to use it! It seems really powerful but I am struggling to use it. I made a copy of my server to show my problem. I just tried the climbing Client <-> Server example and its not working for me 😥. (https://github.com/micaww/rage-rpc#server-to-client) Server:(i cuted unrelevant things out. its freeroam with some CEF) -> Clientside: I used: const rpc = require('rage-rpc'); rpc.register('getIsClimbing', () => mp.players.local.isClimbing()); In "client_packages\freeroam\index.js" and: const rpc = require('rage-rpc'); rpc.callClient(player, 'getIsClimbing').then(climbing => { if(climbing){ console.log('The player is climbing!'); }else{ console.log('The player is not climbing!'); } }); inside "packages\freeroam\events.js" i created a "rage-rpc" Folder with a index.js of rage-rpc.min.js cause i can't use const rpc = require('rage-rpc'); in client_packages for some reason? it gets me this: I hope for Help i believe its a stupid thingi am doing wrong 🙄 Hank Share this post Link to post Share on other sites
micaww 32 Posted June 2 Version 0.3.0 has been released! Sorry everyone for the wait. RPC has been holding up very well and is being used heavily by quite a few people even without updating. Nevertheless, I bring you some more features and bug fixes! https://github.com/micaww/rage-rpc/releases/tag/v0.3.0 1. Added default export The default export has been added thanks to @Yiin which makes it easier to import RPC and get going: // wildcard import using bundler import * as rpc from 'rage-rpc'; // wildcard import using minified build import * as rpc from './rage-rpc.min.js'; // default import import rpc from 'rage-rpc'; // or import rpc from './rage-rpc.min.js'; 2. Added event system There is now an event system that uses the same underlying technology that RPC uses to send messages back and forth between contexts. It can be used as a full-on replacement for the default RAGE:MP events, and it uses nearly the same syntax as the procedure calling functions. The difference between events and procedure calls is: * An event can have any number of listeners on any context, or none. * Triggering an event does not return the result of events. Since it uses the same syntax as the procedure calling API, it's more convenient than using mp.events.add everywhere if you're already using RPC. Also, you can call directly from browser -> server, vice versa, or from browser -> other browsers without intermediate events. Here is a quick run down of the API: Registering Events On any context, you can register and unregister any number of event listeners for an event, similar to the mp.events.add and mp.events.remove API: import rpc from 'rage-rpc'; const handleEvent = (message) => { console.log('event handled: '+message); }; // register the event rpc.on('coolEvent', handleEvent); // later on maybe... // unregister the event handler rpc.off('coolEvent', handleEvent); Calling Events Events can be called from any context and directed towards any context. The API is identical to calling a remote procedure, except that they do not return anything. Events are fire-and-forget, as in they do not return any results or errors: // serverside rpc.on('serverEvent', (msg, {player}) => console.log(`message from ${player.name}: ${msg}`)); rpc.triggerClient(mp.players.at(0), 'clientEvent'); rpc.triggerBrowsers(mp.players.at(0), 'browserEvent'); // clientside rpc.on('clientEvent', () => { // set the player to ragdoll mp.players.local.setToRagdoll(1000, 10000, 0, false, false, false); }); rpc.trigger('clientEvent'); rpc.triggerServer('serverEvent', 'hello!!'); rpc.triggerBrowsers('browserEvent', 'aaaahhh'); rpc.triggerBrowser(browser, 'browserEvent', 'yoyoyo'); // browser rpc.on('browserEvent1', () => { if(confirm('Do you want to ragdoll?')){ rpc.triggerClient('clientEvent'); // ragdoll them! } }); rpc.on('browserEvent2', msg => alert(msg)); rpc.trigger('browserEvent2', 'hello world!'); rpc.triggerServer('serverEvent', 'hey from browser'); rpc.triggerBrowsers('browserEvent1'); Using these events in the place of RPC functions is recommended when you don't need a result back, as it prevents the local context from keeping track of the called procedure and prevents the remote context from returning data back, which makes it outperform typical RPCs that must send information back to the caller. 3. Added options to procedure calls Some options have been added to the procedure calls (not available on events) that give you some more control over the events that you're calling: * noRet: boolean - Prevent the remote context from sending return data. This saves bandwidth when a response isn't needed. Similar to how events work. * timeout: number - A timeout, in milliseconds, for the procedure call to run. If the procedure takes longer to return than this time, the promise will reject with "TIMEOUT". 4. Added generic types to procedure calls (TypeScript) Also thanks to @Yiin , if you're using TypeScript, you can now specify the resolution type of the returned Promise using generics: // some procedure registering rpc.register('getTheNumber', () => 42); // calling that procedure rpc.call<number>('getTheNumber').then(num => { // "num" is the number type }); Other Bug Fixes * Fix sending incorrect entity sometimes from client->server: Sometimes the client would send the wrong MP entity to the server in certain rare situations. * Fix persisting browserId in CEF: Allows for page reloading without messing up RPC knowing which browser to send events to. 3 Share this post Link to post Share on other sites