Add initial client<-->server RPC
This commit is contained in:
parent
1edbf7ffa4
commit
dc0d914b27
10
package.json
10
package.json
@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "rage-eventbus",
|
"name": "rage-rpc",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "An asynchronous event bus for RAGE Multiplayer",
|
"description": "An asynchronous RPC implementation for RAGE Multiplayer",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/micaww/rage-eventbus.git"
|
"url": "git+https://github.com/micaww/rage-rpc.git"
|
||||||
},
|
},
|
||||||
"author": "micaww",
|
"author": "micaww",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/micaww/rage-eventbus/issues"
|
"url": "https://github.com/micaww/rage-rpc/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/micaww/rage-eventbus#readme",
|
"homepage": "https://github.com/micaww/rage-rpc#readme",
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
|
178
src/index.js
178
src/index.js
@ -1,63 +1,163 @@
|
|||||||
const util = require('./util.js');
|
const util = require('./util.js');
|
||||||
|
|
||||||
//const isClient = !!mp.game.joaat;
|
const environment = util.getEnvironment();
|
||||||
//const isCEF = !!mp.trigger;
|
if(!environment) throw 'Unknown RAGE environment';
|
||||||
|
|
||||||
|
const PROCESS_EVENT = '__rpc:process';
|
||||||
|
|
||||||
|
const rpc = {};
|
||||||
|
|
||||||
const listeners = {};
|
const listeners = {};
|
||||||
|
const pending = {};
|
||||||
|
|
||||||
/*mp.events.add('rbus:process', (data) => {
|
async function callProcedure(name, args, info){
|
||||||
|
if(!listeners[name]) throw 'PROCEDURE_NOT_FOUND';
|
||||||
|
return listeners[name](args, info);
|
||||||
|
}
|
||||||
|
|
||||||
});*/
|
const processEvent = (...args) => {
|
||||||
|
let data = args[0];
|
||||||
|
if(environment === "server") data = args[1];
|
||||||
|
data = util.parseData(data);
|
||||||
|
|
||||||
const rbus = {};
|
if(data.req){ // someone is trying to remotely call a procedure
|
||||||
|
const info = {
|
||||||
|
id: data.id,
|
||||||
|
environment: data.env
|
||||||
|
};
|
||||||
|
if(environment === "server") info.player = args[0];
|
||||||
|
const promise = callProcedure(data.name, data.args, info);
|
||||||
|
switch(environment){
|
||||||
|
case "server": {
|
||||||
|
promise.then(res => {
|
||||||
|
info.player.call(PROCESS_EVENT, [util.stringifyData({
|
||||||
|
ret: 1,
|
||||||
|
id: data.id,
|
||||||
|
res
|
||||||
|
})]);
|
||||||
|
}).catch(err => {
|
||||||
|
info.player.call(PROCESS_EVENT, [util.stringifyData({
|
||||||
|
ret: 1,
|
||||||
|
id: data.id,
|
||||||
|
err
|
||||||
|
})]);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "client": {
|
||||||
|
promise.then(res => {
|
||||||
|
mp.events.callRemote(PROCESS_EVENT, util.stringifyData({
|
||||||
|
ret: 1,
|
||||||
|
id: data.id,
|
||||||
|
res
|
||||||
|
}));
|
||||||
|
}).catch(err => {
|
||||||
|
mp.events.callRemote(PROCESS_EVENT, util.stringifyData({
|
||||||
|
ret: 1,
|
||||||
|
id: data.id,
|
||||||
|
err
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if(data.ret){ // a previously called remote procedure has returned
|
||||||
|
const info = pending[data.id];
|
||||||
|
if(info){
|
||||||
|
if(data.err) info.reject(data.err);
|
||||||
|
else info.resolve(data.res);
|
||||||
|
pending[data.id] = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mp.events.add(PROCESS_EVENT, processEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register an event listener.
|
* Register a procedure.
|
||||||
* @param {string} eventName - The name of the event.
|
* @param {string} name - The name of the procedure.
|
||||||
* @param {function} cb - The event's callback. The return value will be sent back to the caller.
|
* @param {function} cb - The procedure's callback. The return value will be sent back to the caller.
|
||||||
*/
|
*/
|
||||||
rbus.on = (eventName, cb) => {
|
rpc.register = (name, cb) => {
|
||||||
if(!listeners[eventName]) listeners[eventName] = [];
|
listeners[name] = cb;
|
||||||
listeners[eventName].push(cb);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister an event listener.
|
* Unregister a procedure.
|
||||||
* @param {string} eventName - The name of the event.
|
* @param {string} name - The name of the procedure.
|
||||||
* @param {function} cb - The callback that was registered with `on`.
|
|
||||||
*/
|
*/
|
||||||
rbus.off = (eventName, cb) => {
|
rpc.unregister = (name) => {
|
||||||
if(!listeners[eventName]) return;
|
listeners[name] = undefined;
|
||||||
listeners[eventName] = listeners[eventName].filter(listener => listener !== cb);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls a local event listener.
|
* Calls a local procedure.
|
||||||
* @param {string} eventName - The name of the event.
|
* @param {string} name - The name of the locally registered procedure.
|
||||||
* @returns {Promise} - The result from the local event listener.
|
* @param args - Any parameters for the procedure.
|
||||||
|
* @returns {Promise} - The result from the procedure.
|
||||||
*/
|
*/
|
||||||
rbus.send = (eventName) => {
|
rpc.call = (name, args) => callProcedure(name, args, { environment });
|
||||||
if(!listeners[eventName] || !listeners[eventName].length) return Promise.reject('NO_LISTENERS');
|
|
||||||
return Promise.resolve(listeners[eventName][0]());
|
/**
|
||||||
|
* Calls a remote procedure registered on the server.
|
||||||
|
* @param {string} name - The name of the registered procedure.
|
||||||
|
* @param args - Any parameters for the procedure.
|
||||||
|
* @returns {Promise} - The result from the procedure.
|
||||||
|
*/
|
||||||
|
rpc.callServer = (name, args) => {
|
||||||
|
switch(environment){
|
||||||
|
case "server": {
|
||||||
|
return rpc.call(name, args);
|
||||||
|
}
|
||||||
|
case "client": {
|
||||||
|
const id = util.uid();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
pending[id] = {
|
||||||
|
resolve,
|
||||||
|
reject
|
||||||
|
};
|
||||||
|
mp.events.callRemote(PROCESS_EVENT, util.stringifyData({
|
||||||
|
req: 1,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
env: environment,
|
||||||
|
args
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls a remote event listener residing on the server.
|
* Calls a remote procedure registered on the client.
|
||||||
* @param {string} eventName - The name of the event.
|
* @param player - The player to call the procedure on.
|
||||||
* @returns {Promise} - The result from the remote event listener.
|
* @param {string} name - The name of the registered procedure.
|
||||||
|
* @param args - Any parameters for the procedure.
|
||||||
|
* @returns {Promise} - The result from the procedure.
|
||||||
*/
|
*/
|
||||||
rbus.sendServer = (eventName) => {
|
rpc.callClient = (player, name, args) => {
|
||||||
|
switch(environment){
|
||||||
|
case "client": {
|
||||||
|
if(player === mp.players.local) return rpc.call(name, args);
|
||||||
|
else return Promise.reject('Only the server can RPC to other clients.');
|
||||||
|
}
|
||||||
|
case "server": {
|
||||||
|
const id = util.uid();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
pending[id] = {
|
||||||
|
resolve,
|
||||||
|
reject
|
||||||
|
};
|
||||||
|
player.call(PROCESS_EVENT, [util.stringifyData({
|
||||||
|
req: 1,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
env: environment,
|
||||||
|
args
|
||||||
|
})]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
module.exports = rpc;
|
||||||
* Calls a remote event listener residing on the client.
|
|
||||||
* @param player - The player to send to
|
|
||||||
* @param {string} eventName - The name of the event
|
|
||||||
* @returns {Promise} - The result from the remote event listener
|
|
||||||
*/
|
|
||||||
rbus.sendClient = (player, eventName) => {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = rbus;
|
|
19
src/util.js
19
src/util.js
@ -3,9 +3,24 @@ const util = {};
|
|||||||
util.uid = () => {
|
util.uid = () => {
|
||||||
let firstPart = (Math.random() * 46656) | 0;
|
let firstPart = (Math.random() * 46656) | 0;
|
||||||
let secondPart = (Math.random() * 46656) | 0;
|
let secondPart = (Math.random() * 46656) | 0;
|
||||||
firstPart = ("000" + firstPart.toString(36)).slice(-3);
|
firstPart = ('000' + firstPart.toString(36)).slice(-3);
|
||||||
secondPart = ("000" + secondPart.toString(36)).slice(-3);
|
secondPart = ('000' + secondPart.toString(36)).slice(-3);
|
||||||
return firstPart + secondPart;
|
return firstPart + secondPart;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
util.getEnvironment = () => {
|
||||||
|
if(!mp) return undefined;
|
||||||
|
if(mp.joaat) return 'server';
|
||||||
|
else if(mp.game && mp.game.joaat) return 'client';
|
||||||
|
else if(mp.trigger) return 'cef';
|
||||||
|
};
|
||||||
|
|
||||||
|
util.stringifyData = (data) => {
|
||||||
|
return JSON.stringify(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
util.parseData = (data) => {
|
||||||
|
return JSON.parse(data);
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = util;
|
module.exports = util;
|
Reference in New Issue
Block a user