diff --git a/dist/rage-rpc.d.ts b/dist/rage-rpc.d.ts index 63ce9c5..c0efa10 100644 --- a/dist/rage-rpc.d.ts +++ b/dist/rage-rpc.d.ts @@ -2,13 +2,13 @@ export as namespace rpc; export function register(name: string, cb: ProcedureListener): void; export function unregister(name: string): void; -export function call(name: string, args?: any): Promise; -export function callServer(name: string, args?: any): Promise; -export function callClient(player: Player, name: string, args?: any): Promise; -export function callClient(name: string, args?: any): Promise; -export function callBrowsers(player: Player, name: string, args?: any): Promise; -export function callBrowsers(name: string, args?: any): Promise; -export function callBrowser(browser: Browser, name: string, args?: any): Promise; +export function call(name: string, args?: any, options: CallOptions = {}): Promise; +export function callServer(name: string, args?: any, options: CallOptions = {}): Promise; +export function callClient(player: Player, name: string, args?: any, options: CallOptions = {}): Promise; +export function callClient(name: string, args?: any, options: CallOptions = {}): Promise; +export function callBrowsers(player: Player, name: string, args?: any, options: CallOptions = {}): Promise; +export function callBrowsers(name: string, args?: any, options: CallOptions = {}): Promise; +export function callBrowser(browser: Browser, name: string, args?: any, options: CallOptions = {}): Promise; export interface Player { call: (eventName: string, args?: any[]) => void; @@ -26,4 +26,9 @@ export interface ProcedureListenerInfo { player?: Player; } +export interface CallOptions { + timeout?: number; + noRet?: boolean; +} + export type ProcedureListener = (args: any, info: ProcedureListenerInfo) => any; diff --git a/dist/rage-rpc.min.js b/dist/rage-rpc.min.js index a396280..44ef4e8 100644 --- a/dist/rage-rpc.min.js +++ b/dist/rage-rpc.min.js @@ -1 +1,135 @@ -!function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports=r():e.rpc=r()}("undefined"!=typeof self?self:this,function(){return function(e){var r={};function n(t){if(r[t])return r[t].exports;var c=r[t]={i:t,l:!1,exports:{}};return e[t].call(c.exports,c,c.exports,n),c.l=!0,c.exports}return n.m=e,n.c=r,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,r){if(1&r&&(e=n(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(n.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var c in e)n.d(t,c,function(r){return e[r]}.bind(null,c));return t},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},n.p="",n(n.s=1)}([function(e,r,n){"use strict";var t;function c(e,r){const n="client"===o();if(e&&"object"==typeof e&&void 0!==e.id){const c=(r,t,c)=>n?e.type===r&&t.at(e.id)===e:e instanceof c;switch(r){case t.Blip:return c("blip",mp.blips,mp.Blip);case t.Checkpoint:return c("checkpoint",mp.checkpoints,mp.Checkpoint);case t.Colshape:return c("colshape",mp.colshapes,mp.Colshape);case t.Label:return c("textlabel",mp.labels,mp.TextLabel);case t.Marker:return c("marker",mp.markers,mp.Marker);case t.Object:return c("object",mp.objects,mp.Object);case t.Pickup:return c("pickup",mp.pickups,mp.Pickup);case t.Player:return c("player",mp.players,mp.Player);case t.Vehicle:return c("vehicle",mp.vehicles,mp.Vehicle)}}return!1}function s(){const e=46656*Math.random()|0,r=46656*Math.random()|0;return("000"+e.toString(36)).slice(-3)+("000"+r.toString(36)).slice(-3)}function o(){return mp.joaat?"server":mp.game&&mp.game.joaat?"client":mp.trigger?"cef":void 0}function i(e){const r=o();return JSON.stringify(e,(e,n)=>{if("client"===r||"server"===r&&n&&"object"==typeof n){let e;if(c(n,t.Blip)?e=t.Blip:c(n,t.Checkpoint)?e=t.Checkpoint:c(n,t.Colshape)?e=t.Colshape:c(n,t.Marker)?e=t.Marker:c(n,t.Object)?e=t.Object:c(n,t.Pickup)?e=t.Pickup:c(n,t.Player)?e=t.Player:c(n,t.Vehicle)&&(e=t.Vehicle),e)return{__t:e,i:n.remoteId||n.id}}return n})}function a(e){const r=o();return JSON.parse(e,(e,n)=>{if(("client"===r||"server"===r)&&n&&"object"==typeof n&&"string"==typeof n.__t&&"number"==typeof n.i&&2===Object.keys(n).length){const e=n.i;let c;switch(n.__t){case t.Blip:c=mp.blips;break;case t.Checkpoint:c=mp.checkpoints;break;case t.Colshape:c=mp.colshapes;break;case t.Label:c=mp.labels;break;case t.Marker:c=mp.markers;break;case t.Object:c=mp.objects;break;case t.Pickup:c=mp.pickups;break;case t.Player:c=mp.players;break;case t.Vehicle:c=mp.vehicles}if(c)return c["client"===r?"atRemoteId":"at"](e)}return n})}function l(e){return new Promise(r=>setTimeout(()=>r(e),0))}function p(e){return new Promise((r,n)=>setTimeout(()=>n(e),0))}function u(e){try{e.url}catch(e){return!1}return!0}n.d(r,"g",function(){return s}),n.d(r,"a",function(){return o}),n.d(r,"f",function(){return i}),n.d(r,"c",function(){return a}),n.d(r,"e",function(){return l}),n.d(r,"d",function(){return p}),n.d(r,"b",function(){return u}),function(e){e.Blip="b",e.Checkpoint="cp",e.Colshape="c",e.Label="l",e.Marker="m",e.Object="o",e.Pickup="p",e.Player="pl",e.Vehicle="v"}(t||(t={}))},function(e,r,n){"use strict";n.r(r),function(e){n.d(r,"register",function(){return d}),n.d(r,"unregister",function(){return m}),n.d(r,"call",function(){return g}),n.d(r,"callServer",function(){return _}),n.d(r,"callClient",function(){return b}),n.d(r,"callBrowsers",function(){return y}),n.d(r,"callBrowser",function(){return k});var t=n(0);const c=t.a();if(!c)throw"Unknown RAGE environment";const s="PROCEDURE_NOT_FOUND",o="__rpc:id",i="__rpc:process",a="__rpc:browserRegister",l="__rpc:browserUnregister",p="cef"===c?window:e;if(!p[i])if(p.__rpcListeners={},p.__rpcPending={},p[i]=((e,r)=>{"server"!==c&&(r=e);const n=t.c(r);if(n.req){const r={id:n.id,environment:n.fenv||n.env};"server"===c&&(r.player=e);const s={ret:1,id:n.id,env:c};let o;switch(c){case"server":o=(e=>r.player.call(i,[t.f(e)]));break;case"client":if("server"===n.env)o=(e=>mp.events.callRemote(i,t.f(e)));else if("cef"===n.env){const e=n.b&&p.__rpcBrowsers[n.b];r.browser=e,o=(r=>e&&t.b(e)&&u(e,r,!0))}break;case"cef":o=(e=>mp.trigger(i,t.f(e)))}o&&f(n.name,n.args,r).then(e=>o({...s,res:e})).catch(e=>o({...s,err:e}))}else if(n.ret){const r=p.__rpcPending[n.id];if("server"===c&&r.player!==e)return;r&&(r.resolve(n.err?t.d(n.err):t.e(n.res)),delete p.__rpcPending[n.id])}}),"cef"!==c){if(mp.events.add(i,p[i]),"client"===c){d("__rpc:callServer",([e,r],n)=>h(e,r,{fenv:n.environment})),d("__rpc:callBrowsers",([e,r],n)=>w(null,e,r,{fenv:n.environment})),p.__rpcBrowsers={};const e=e=>{const r=t.g();Object.keys(p.__rpcBrowsers).forEach(r=>{const n=p.__rpcBrowsers[r];n&&t.b(n)&&n!==e||delete p.__rpcBrowsers[r]}),p.__rpcBrowsers[r]=e,e.execute(`if(typeof window['${o}'] === 'undefined'){ window['${o}'] = Promise.resolve('${r}'); }else{ window['${o}:resolve']('${r}'); }`)};mp.browsers.forEach(e),mp.events.add("browserCreated",e),p.__rpcBrowserProcedures={},mp.events.add(a,e=>{const[r,n]=JSON.parse(e);p.__rpcBrowserProcedures[n]=r}),mp.events.add(l,e=>{const[r,n]=JSON.parse(e);p.__rpcBrowserProcedures[n]===r&&delete p.__rpcBrowserProcedures[n]})}}else void 0===p[o]&&(p[o]=new Promise(e=>{p[o+":resolve"]=e}));function u(e,r,n){const c=t.f(r);e.execute(`var process = window["${i}"]; if(process){ process(${JSON.stringify(c)}); }else{ ${n?"":`mp.trigger("${i}", '{"ret":1,"id":"${r.id}","err":"${s}","env":"cef"}');`} }`)}function f(e,r,n){const c=p.__rpcListeners[e];return c?t.e(c(r,n)):t.d(s)}function d(e,r){if(2!==arguments.length)throw'register expects 2 arguments: "name" and "cb"';"cef"===c&&p[o].then(r=>mp.trigger(a,JSON.stringify([r,e]))),p.__rpcListeners[e]=r}function m(e){if(1!==arguments.length)throw'unregister expects 1 argument: "name"';"cef"===c&&p[o].then(r=>mp.trigger(l,JSON.stringify([r,e]))),p.__rpcListeners[e]=void 0}function g(e,r){return 1!==arguments.length&&2!==arguments.length?t.d('call expects 1 or 2 arguments: "name" and optional "args"'):f(e,r,{environment:c})}function h(e,r,n={}){switch(c){case"server":return g(e,r);case"client":{const s=t.g();return new Promise(o=>{p.__rpcPending[s]={resolve:o};const a={req:1,id:s,name:e,env:c,args:r,...n};mp.events.callRemote(i,t.f(a))})}case"cef":return b("__rpc:callServer",[e,r])}}function _(e,r){return 1!==arguments.length&&2!==arguments.length?t.d('callServer expects 1 or 2 arguments: "name" and optional "args"'):h(e,r,{})}function b(e,r,n){switch(c){case"client":return n=r,r=e,1!==arguments.length&&2!==arguments.length||"string"!=typeof r?t.d('callClient from the client expects 1 or 2 arguments: "name" and optional "args"'):g(r,n);case"server":{if(2!==arguments.length&&3!==arguments.length||"object"!=typeof e)return t.d('callClient from the server expects 2 or 3 arguments: "player", "name", and optional "args"');const s=t.g();return new Promise(o=>{p.__rpcPending[s]={resolve:o,player:e};const a={req:1,id:s,name:r,env:c,args:n};e.call(i,[t.f(a)])})}case"cef":{if(n=r,r=e,1!==arguments.length&&2!==arguments.length||"string"!=typeof r)return t.d('callClient from the browser expects 1 or 2 arguments: "name" and optional "args"');const s=t.g();return p[o].then(e=>new Promise(o=>{p.__rpcPending[s]={resolve:o};const a={b:e,req:1,id:s,name:r,env:c,args:n};mp.trigger(i,t.f(a))}))}}}function v(e,r,n,t,s={}){return new Promise(o=>{p.__rpcPending[e]={resolve:o},u(r,{req:1,id:e,name:n,env:c,args:t,...s},!1)})}function w(e,r,n,o={}){switch(c){case"client":const i=t.g(),a=p.__rpcBrowserProcedures[r];if(!a)return t.d(s);const l=p.__rpcBrowsers[a];return l&&t.b(l)?v(i,l,r,n,o):t.d(s);case"server":return b(e,"__rpc:callBrowsers",[r,n]);case"cef":return b("__rpc:callBrowsers",[r,n])}}function y(e,r,n){switch(c){case"client":case"cef":return 1!==arguments.length&&2!==arguments.length?t.d('callBrowsers from the client or browser expects 1 or 2 arguments: "name" and optional "args"'):w(null,e,r,{});case"server":return 2!==arguments.length&&3!==arguments.length?t.d('callBrowsers from the server expects 2 or 3 arguments: "player", "name", and optional "args"'):w(e,r,n,{})}}function k(e,r,n){if("client"!==c)return t.d("callBrowser can only be used in the client environment");if(2!==arguments.length&&3!==arguments.length)return t.d('callBrowser expects 2 or 3 arguments: "browser", "name", and optional "args"');return v(t.g(),e,r,n,{})}}.call(this,n(2))},function(e,r){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n}])}); \ No newline at end of file +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports = factory(); + else + root["rpc"] = factory(); +})(typeof self !== 'undefined' ? self : this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./src/index.ts"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./node_modules/webpack/buildin/global.js": +/*!***********************************!*\ + !*** (webpack)/buildin/global.js ***! + \***********************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n\n\n//# sourceURL=webpack://rpc/(webpack)/buildin/global.js?"); + +/***/ }), + +/***/ "./src/index.ts": +/*!**********************!*\ + !*** ./src/index.ts ***! + \**********************/ +/*! exports provided: register, unregister, call, callServer, callClient, callBrowsers, callBrowser, default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* WEBPACK VAR INJECTION */(function(global) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"register\", function() { return register; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"unregister\", function() { return unregister; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"call\", function() { return call; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"callServer\", function() { return callServer; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"callClient\", function() { return callClient; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"callBrowsers\", function() { return callBrowsers; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"callBrowser\", function() { return callBrowser; });\n/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./util */ \"./src/util.ts\");\n\nconst environment = _util__WEBPACK_IMPORTED_MODULE_0__[\"getEnvironment\"]();\nif (!environment) throw 'Unknown RAGE environment';\nconst ERR_NOT_FOUND = 'PROCEDURE_NOT_FOUND';\nconst IDENTIFIER = '__rpc:id';\nconst PROCESS_EVENT = '__rpc:process';\nconst BROWSER_REGISTER = '__rpc:browserRegister';\nconst BROWSER_UNREGISTER = '__rpc:browserUnregister';\nconst glob = environment === \"cef\" ? window : global;\n\nif (!glob[PROCESS_EVENT]) {\n glob.__rpcListeners = {};\n glob.__rpcPending = {};\n\n glob[PROCESS_EVENT] = (player, rawData) => {\n if (environment !== \"server\") rawData = player;\n const data = _util__WEBPACK_IMPORTED_MODULE_0__[\"parseData\"](rawData);\n\n if (data.req) {\n // someone is trying to remotely call a procedure\n const info = {\n id: data.id,\n environment: data.fenv || data.env\n };\n if (environment === \"server\") info.player = player;\n const part = {\n ret: 1,\n id: data.id,\n env: environment\n };\n let ret;\n\n switch (environment) {\n case \"server\":\n ret = ev => info.player.call(PROCESS_EVENT, [_util__WEBPACK_IMPORTED_MODULE_0__[\"stringifyData\"](ev)]);\n\n break;\n\n case \"client\":\n {\n if (data.env === \"server\") {\n ret = ev => mp.events.callRemote(PROCESS_EVENT, _util__WEBPACK_IMPORTED_MODULE_0__[\"stringifyData\"](ev));\n } else if (data.env === \"cef\") {\n const browser = data.b && glob.__rpcBrowsers[data.b];\n info.browser = browser;\n\n ret = ev => browser && _util__WEBPACK_IMPORTED_MODULE_0__[\"isBrowserValid\"](browser) && passEventToBrowser(browser, ev, true);\n }\n\n break;\n }\n\n case \"cef\":\n {\n ret = ev => mp.trigger(PROCESS_EVENT, _util__WEBPACK_IMPORTED_MODULE_0__[\"stringifyData\"](ev));\n }\n }\n\n if (ret) {\n const promise = callProcedure(data.name, data.args, info);\n if (!data.noRet) promise.then(res => ret({ ...part,\n res\n })).catch(err => ret({ ...part,\n err\n }));\n }\n } else if (data.ret) {\n // a previously called remote procedure has returned\n const info = glob.__rpcPending[data.id];\n if (environment === \"server\" && info.player !== player) return;\n\n if (info) {\n info.resolve(data.err ? _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"](data.err) : _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseResolve\"](data.res));\n delete glob.__rpcPending[data.id];\n }\n }\n };\n\n if (environment !== \"cef\") {\n mp.events.add(PROCESS_EVENT, glob[PROCESS_EVENT]);\n\n if (environment === \"client\") {\n // set up internal pass-through events\n register('__rpc:callServer', ([name, args, noRet], info) => _callServer(name, args, {\n fenv: info.environment,\n noRet\n }));\n register('__rpc:callBrowsers', ([name, args, noRet], info) => _callBrowsers(null, name, args, {\n fenv: info.environment,\n noRet\n })); // set up browser identifiers\n\n glob.__rpcBrowsers = {};\n\n const initBrowser = browser => {\n const id = _util__WEBPACK_IMPORTED_MODULE_0__[\"uid\"]();\n Object.keys(glob.__rpcBrowsers).forEach(key => {\n const b = glob.__rpcBrowsers[key];\n if (!b || !_util__WEBPACK_IMPORTED_MODULE_0__[\"isBrowserValid\"](b) || b === browser) delete glob.__rpcBrowsers[key];\n });\n glob.__rpcBrowsers[id] = browser;\n browser.execute(`\n window.name = '${id}';\n if(typeof window['${IDENTIFIER}'] === 'undefined'){\n window['${IDENTIFIER}'] = Promise.resolve(window.name);\n }else{\n window['${IDENTIFIER}:resolve'](window.name);\n }\n `);\n };\n\n mp.browsers.forEach(initBrowser);\n mp.events.add('browserCreated', initBrowser); // set up browser registration map\n\n glob.__rpcBrowserProcedures = {};\n mp.events.add(BROWSER_REGISTER, data => {\n const [browserId, name] = JSON.parse(data);\n glob.__rpcBrowserProcedures[name] = browserId;\n });\n mp.events.add(BROWSER_UNREGISTER, data => {\n const [browserId, name] = JSON.parse(data);\n if (glob.__rpcBrowserProcedures[name] === browserId) delete glob.__rpcBrowserProcedures[name];\n });\n }\n } else {\n if (typeof glob[IDENTIFIER] === 'undefined') {\n glob[IDENTIFIER] = new Promise(resolve => {\n if (window.name) {\n resolve(window.name);\n } else {\n glob[IDENTIFIER + ':resolve'] = resolve;\n }\n });\n }\n }\n}\n\nfunction passEventToBrowser(browser, data, ignoreNotFound) {\n const raw = _util__WEBPACK_IMPORTED_MODULE_0__[\"stringifyData\"](data);\n browser.execute(`var process = window[\"${PROCESS_EVENT}\"]; if(process){ process(${JSON.stringify(raw)}); }else{ ${ignoreNotFound ? '' : `mp.trigger(\"${PROCESS_EVENT}\", '{\"ret\":1,\"id\":\"${data.id}\",\"err\":\"${ERR_NOT_FOUND}\",\"env\":\"cef\"}');`} }`);\n}\n\nfunction callProcedure(name, args, info) {\n const listener = glob.__rpcListeners[name];\n if (!listener) return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"](ERR_NOT_FOUND);\n return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseResolve\"](listener(args, info));\n}\n/**\r\n * Register a procedure.\r\n * @param {string} name - The name of the procedure.\r\n * @param {function} cb - The procedure's callback. The return value will be sent back to the caller.\r\n */\n\n\nfunction register(name, cb) {\n if (arguments.length !== 2) throw 'register expects 2 arguments: \"name\" and \"cb\"';\n if (environment === \"cef\") glob[IDENTIFIER].then(id => mp.trigger(BROWSER_REGISTER, JSON.stringify([id, name])));\n glob.__rpcListeners[name] = cb;\n}\n/**\r\n * Unregister a procedure.\r\n * @param {string} name - The name of the procedure.\r\n */\n\nfunction unregister(name) {\n if (arguments.length !== 1) throw 'unregister expects 1 argument: \"name\"';\n if (environment === \"cef\") glob[IDENTIFIER].then(id => mp.trigger(BROWSER_UNREGISTER, JSON.stringify([id, name])));\n glob.__rpcListeners[name] = undefined;\n}\n/**\r\n * Calls a local procedure. Only procedures registered in the same context will be resolved.\r\n *\r\n * Can be called from any environment.\r\n *\r\n * @param name - The name of the locally registered procedure.\r\n * @param args - Any parameters for the procedure.\r\n * @param options - Any options.\r\n * @returns The result from the procedure.\r\n */\n\nfunction call(name, args, options = {}) {\n if (arguments.length < 1 || arguments.length > 3) return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"]('call expects 1 to 3 arguments: \"name\", optional \"args\", and optional \"options\"');\n return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseTimeout\"](callProcedure(name, args, {\n environment\n }), options.timeout);\n}\n\nfunction _callServer(name, args, extraData = {}) {\n switch (environment) {\n case \"server\":\n {\n return call(name, args);\n }\n\n case \"client\":\n {\n const id = _util__WEBPACK_IMPORTED_MODULE_0__[\"uid\"]();\n return new Promise(resolve => {\n if (!extraData.noRet) {\n glob.__rpcPending[id] = {\n resolve\n };\n }\n\n const event = {\n req: 1,\n id,\n name,\n env: environment,\n args,\n ...extraData\n };\n mp.events.callRemote(PROCESS_EVENT, _util__WEBPACK_IMPORTED_MODULE_0__[\"stringifyData\"](event));\n });\n }\n\n case \"cef\":\n {\n return callClient('__rpc:callServer', [name, args, +extraData.noRet]);\n }\n }\n}\n/**\r\n * Calls a remote procedure registered on the server.\r\n *\r\n * Can be called from any environment.\r\n *\r\n * @param name - The name of the registered procedure.\r\n * @param args - Any parameters for the procedure.\r\n * @param options - Any options.\r\n * @returns The result from the procedure.\r\n */\n\n\nfunction callServer(name, args, options = {}) {\n if (arguments.length < 1 || arguments.length > 3) return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"]('callServer expects 1 to 3 arguments: \"name\", optional \"args\", and optional \"options\"');\n let extraData = {};\n if (options.noRet) extraData.noRet = 1;\n return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseTimeout\"](_callServer(name, args, extraData), options.timeout);\n}\n\nfunction _callClient(player, name, args, extraData = {}) {\n switch (environment) {\n case 'client':\n {\n return call(name, args);\n }\n\n case 'server':\n {\n const id = _util__WEBPACK_IMPORTED_MODULE_0__[\"uid\"]();\n return new Promise(resolve => {\n if (!extraData.noRet) {\n glob.__rpcPending[id] = {\n resolve,\n player\n };\n }\n\n const event = {\n req: 1,\n id,\n name,\n env: environment,\n args,\n ...extraData\n };\n player.call(PROCESS_EVENT, [_util__WEBPACK_IMPORTED_MODULE_0__[\"stringifyData\"](event)]);\n });\n }\n\n case 'cef':\n {\n const id = _util__WEBPACK_IMPORTED_MODULE_0__[\"uid\"]();\n return glob[IDENTIFIER].then(browserId => {\n return new Promise(resolve => {\n if (!extraData.noRet) {\n glob.__rpcPending[id] = {\n resolve\n };\n }\n\n const event = {\n b: browserId,\n req: 1,\n id,\n name,\n env: environment,\n args,\n ...extraData\n };\n mp.trigger(PROCESS_EVENT, _util__WEBPACK_IMPORTED_MODULE_0__[\"stringifyData\"](event));\n });\n });\n }\n }\n}\n/**\r\n * Calls a remote procedure registered on the client.\r\n *\r\n * Can be called from any environment.\r\n *\r\n * @param player - The player to call the procedure on.\r\n * @param name - The name of the registered procedure.\r\n * @param args - Any parameters for the procedure.\r\n * @param options - Any options.\r\n * @returns The result from the procedure.\r\n */\n\n\nfunction callClient(player, name, args, options = {}) {\n switch (environment) {\n case 'client':\n {\n options = args || {};\n args = name;\n name = player;\n player = null;\n if (arguments.length < 1 || arguments.length > 3 || typeof name !== 'string') return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"]('callClient from the client expects 1 to 3 arguments: \"name\", optional \"args\", and optional \"options\"');\n break;\n }\n\n case 'server':\n {\n if (arguments.length < 2 || arguments.length > 4 || typeof player !== 'object') return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"]('callClient from the server expects 2 to 4 arguments: \"player\", \"name\", optional \"args\", and optional \"options\"');\n break;\n }\n\n case 'cef':\n {\n options = args || {};\n args = name;\n name = player;\n player = null;\n if (arguments.length < 1 || arguments.length > 3 || typeof name !== 'string') return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"]('callClient from the browser expects 1 to 3 arguments: \"name\", optional \"args\", and optional \"options\"');\n break;\n }\n }\n\n let extraData = {};\n if (options.noRet) extraData.noRet = 1;\n return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseTimeout\"](_callClient(typeof player === 'object' ? player : null, name, args, extraData), options.timeout);\n}\n\nfunction _callBrowser(id, browser, name, args, extraData = {}) {\n return new Promise(resolve => {\n if (!extraData.noRet) {\n glob.__rpcPending[id] = {\n resolve\n };\n }\n\n passEventToBrowser(browser, {\n req: 1,\n id,\n name,\n env: environment,\n args,\n ...extraData\n }, false);\n });\n}\n\nfunction _callBrowsers(player, name, args, extraData = {}) {\n switch (environment) {\n case 'client':\n const id = _util__WEBPACK_IMPORTED_MODULE_0__[\"uid\"]();\n const browserId = glob.__rpcBrowserProcedures[name];\n if (!browserId) return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"](ERR_NOT_FOUND);\n const browser = glob.__rpcBrowsers[browserId];\n if (!browser || !_util__WEBPACK_IMPORTED_MODULE_0__[\"isBrowserValid\"](browser)) return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"](ERR_NOT_FOUND);\n return _callBrowser(id, browser, name, args, extraData);\n\n case 'server':\n return _callClient(player, '__rpc:callBrowsers', [name, args, +extraData.noRet], extraData);\n\n case 'cef':\n return _callClient(null, '__rpc:callBrowsers', [name, args, +extraData.noRet], extraData);\n }\n}\n/**\r\n * Calls a remote procedure registered in any browser context.\r\n *\r\n * Can be called from any environment.\r\n *\r\n * @param player - The player to call the procedure on.\r\n * @param name - The name of the registered procedure.\r\n * @param args - Any parameters for the procedure.\r\n * @param options - Any options.\r\n * @returns The result from the procedure.\r\n */\n\n\nfunction callBrowsers(player, name, args, options = {}) {\n let promise;\n let extraData = {};\n\n switch (environment) {\n case 'client':\n case 'cef':\n options = args || {};\n args = name;\n name = player;\n if (arguments.length < 1 || arguments.length > 3) return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"]('callBrowsers from the client or browser expects 1 to 3 arguments: \"name\", optional \"args\", and optional \"options\"');\n if (options.noRet) extraData.noRet = 1;\n promise = _callBrowsers(null, name, args, extraData);\n break;\n\n case 'server':\n if (arguments.length < 2 || arguments.length > 4) return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"]('callBrowsers from the server expects 2 to 4 arguments: \"player\", \"name\", optional \"args\", and optional \"options\"');\n if (options.noRet) extraData.noRet = 1;\n promise = _callBrowsers(player, name, args, extraData);\n break;\n }\n\n if (promise) {\n return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseTimeout\"](promise, options.timeout);\n }\n}\n/**\r\n * Calls a remote procedure registered in a specific browser instance.\r\n *\r\n * Client-side environment only.\r\n *\r\n * @param browser - The browser instance.\r\n * @param name - The name of the registered procedure.\r\n * @param args - Any parameters for the procedure.\r\n * @param options - Any options.\r\n * @returns The result from the procedure.\r\n */\n\nfunction callBrowser(browser, name, args, options = {}) {\n if (environment !== 'client') return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"]('callBrowser can only be used in the client environment');\n if (arguments.length < 2 || arguments.length > 4) return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseReject\"]('callBrowser expects 2 to 4 arguments: \"browser\", \"name\", optional \"args\", and optional \"options\"');\n const id = _util__WEBPACK_IMPORTED_MODULE_0__[\"uid\"]();\n let extraData = {};\n if (options.noRet) extraData.noRet = 1;\n return _util__WEBPACK_IMPORTED_MODULE_0__[\"promiseTimeout\"](_callBrowser(id, browser, name, args, extraData), options.timeout);\n}\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n register,\n unregister,\n call,\n callServer,\n callClient,\n callBrowsers,\n callBrowser\n});\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../node_modules/webpack/buildin/global.js */ \"./node_modules/webpack/buildin/global.js\")))\n\n//# sourceURL=webpack://rpc/./src/index.ts?"); + +/***/ }), + +/***/ "./src/util.ts": +/*!*********************!*\ + !*** ./src/util.ts ***! + \*********************/ +/*! exports provided: uid, getEnvironment, stringifyData, parseData, promiseResolve, promiseReject, promiseTimeout, isBrowserValid */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"uid\", function() { return uid; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getEnvironment\", function() { return getEnvironment; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"stringifyData\", function() { return stringifyData; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"parseData\", function() { return parseData; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"promiseResolve\", function() { return promiseResolve; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"promiseReject\", function() { return promiseReject; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"promiseTimeout\", function() { return promiseTimeout; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"isBrowserValid\", function() { return isBrowserValid; });\nvar MpTypes;\n\n(function (MpTypes) {\n MpTypes[\"Blip\"] = \"b\";\n MpTypes[\"Checkpoint\"] = \"cp\";\n MpTypes[\"Colshape\"] = \"c\";\n MpTypes[\"Label\"] = \"l\";\n MpTypes[\"Marker\"] = \"m\";\n MpTypes[\"Object\"] = \"o\";\n MpTypes[\"Pickup\"] = \"p\";\n MpTypes[\"Player\"] = \"pl\";\n MpTypes[\"Vehicle\"] = \"v\";\n})(MpTypes || (MpTypes = {}));\n\nfunction isObjectMpType(obj, type) {\n const client = getEnvironment() === 'client';\n\n if (obj && typeof obj === 'object' && typeof obj.id !== 'undefined') {\n const test = (type, collection, mpType) => client ? obj.type === type && collection.at(obj.id) === obj : obj instanceof mpType;\n\n switch (type) {\n case MpTypes.Blip:\n return test('blip', mp.blips, mp.Blip);\n\n case MpTypes.Checkpoint:\n return test('checkpoint', mp.checkpoints, mp.Checkpoint);\n\n case MpTypes.Colshape:\n return test('colshape', mp.colshapes, mp.Colshape);\n\n case MpTypes.Label:\n return test('textlabel', mp.labels, mp.TextLabel);\n\n case MpTypes.Marker:\n return test('marker', mp.markers, mp.Marker);\n\n case MpTypes.Object:\n return test('object', mp.objects, mp.Object);\n\n case MpTypes.Pickup:\n return test('pickup', mp.pickups, mp.Pickup);\n\n case MpTypes.Player:\n return test('player', mp.players, mp.Player);\n\n case MpTypes.Vehicle:\n return test('vehicle', mp.vehicles, mp.Vehicle);\n }\n }\n\n return false;\n}\n\nfunction uid() {\n const first = Math.random() * 46656 | 0;\n const second = Math.random() * 46656 | 0;\n const firstPart = ('000' + first.toString(36)).slice(-3);\n const secondPart = ('000' + second.toString(36)).slice(-3);\n return firstPart + secondPart;\n}\nfunction getEnvironment() {\n if (mp.joaat) return 'server';else if (mp.game && mp.game.joaat) return 'client';else if (mp.trigger) return 'cef';\n}\nfunction stringifyData(data) {\n const env = getEnvironment();\n return JSON.stringify(data, (_, value) => {\n if (env === 'client' || env === 'server' && value && typeof value === 'object') {\n let type;\n if (isObjectMpType(value, MpTypes.Blip)) type = MpTypes.Blip;else if (isObjectMpType(value, MpTypes.Checkpoint)) type = MpTypes.Checkpoint;else if (isObjectMpType(value, MpTypes.Colshape)) type = MpTypes.Colshape;else if (isObjectMpType(value, MpTypes.Marker)) type = MpTypes.Marker;else if (isObjectMpType(value, MpTypes.Object)) type = MpTypes.Object;else if (isObjectMpType(value, MpTypes.Pickup)) type = MpTypes.Pickup;else if (isObjectMpType(value, MpTypes.Player)) type = MpTypes.Player;else if (isObjectMpType(value, MpTypes.Vehicle)) type = MpTypes.Vehicle;\n if (type) return {\n __t: type,\n i: typeof value.remoteId === 'number' ? value.remoteId : value.id\n };\n }\n\n return value;\n });\n}\nfunction parseData(data) {\n const env = getEnvironment();\n return JSON.parse(data, (_, value) => {\n if ((env === 'client' || env === 'server') && value && typeof value === 'object' && typeof value['__t'] === 'string' && typeof value.i === 'number' && Object.keys(value).length === 2) {\n const id = value.i;\n const type = value['__t'];\n let collection;\n\n switch (type) {\n case MpTypes.Blip:\n collection = mp.blips;\n break;\n\n case MpTypes.Checkpoint:\n collection = mp.checkpoints;\n break;\n\n case MpTypes.Colshape:\n collection = mp.colshapes;\n break;\n\n case MpTypes.Label:\n collection = mp.labels;\n break;\n\n case MpTypes.Marker:\n collection = mp.markers;\n break;\n\n case MpTypes.Object:\n collection = mp.objects;\n break;\n\n case MpTypes.Pickup:\n collection = mp.pickups;\n break;\n\n case MpTypes.Player:\n collection = mp.players;\n break;\n\n case MpTypes.Vehicle:\n collection = mp.vehicles;\n break;\n }\n\n if (collection) return collection[env === 'client' ? 'atRemoteId' : 'at'](id);\n }\n\n return value;\n });\n}\nfunction promiseResolve(result) {\n return new Promise(resolve => setTimeout(() => resolve(result), 0));\n}\nfunction promiseReject(error) {\n return new Promise((_, reject) => setTimeout(() => reject(error), 0));\n}\nfunction promiseTimeout(promise, timeout) {\n if (typeof timeout === 'number') {\n return Promise.race([new Promise((_, reject) => {\n setTimeout(() => reject('TIMEOUT'), timeout);\n }), promise]);\n } else return promise;\n}\nfunction isBrowserValid(browser) {\n try {\n browser.url;\n } catch (e) {\n return false;\n }\n\n return true;\n}\n\n//# sourceURL=webpack://rpc/./src/util.ts?"); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/src/defs.d.ts b/src/defs.d.ts index 62a75c8..00cf5bf 100644 --- a/src/defs.d.ts +++ b/src/defs.d.ts @@ -24,6 +24,7 @@ declare interface ProcedureListenerInfo { declare interface CallOptions { timeout?: number; + noRet?: boolean; } declare interface Event { @@ -37,4 +38,5 @@ declare interface Event { fenv?: string; res?: any; err?: any; + noRet?: number; } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 3a64dec..478d533 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,7 +50,10 @@ if(!glob[PROCESS_EVENT]){ ret = ev => mp.trigger(PROCESS_EVENT, util.stringifyData(ev)); } } - if(ret) callProcedure(data.name, data.args, info).then(res => ret({ ...part, res })).catch(err => ret({ ...part, err })); + if(ret){ + const promise = callProcedure(data.name, data.args, info); + if(!data.noRet) promise.then(res => ret({ ...part, res })).catch(err => ret({ ...part, err })); + } }else if(data.ret){ // a previously called remote procedure has returned const info = glob.__rpcPending[data.id]; if(environment === "server" && info.player !== player) return; @@ -66,8 +69,8 @@ if(!glob[PROCESS_EVENT]){ if(environment === "client"){ // set up internal pass-through events - register('__rpc:callServer', ([name, args], info) => _callServer(name, args, { fenv: info.environment })); - register('__rpc:callBrowsers', ([name, args], info) => _callBrowsers(null, name, args, { fenv: info.environment })); + register('__rpc:callServer', ([name, args, noRet], info) => _callServer(name, args, { fenv: info.environment, noRet })); + register('__rpc:callBrowsers', ([name, args, noRet], info) => _callBrowsers(null, name, args, { fenv: info.environment, noRet })); // set up browser identifiers glob.__rpcBrowsers = {}; @@ -161,7 +164,7 @@ export function call(name: string, args?: any, options: CallOptions = {}): Promi return util.promiseTimeout(callProcedure(name, args, { environment }), options.timeout); } -function _callServer(name: string, args?: any, extraData = {}): Promise { +function _callServer(name: string, args?: any, extraData: any = {}): Promise { switch(environment){ case "server": { return call(name, args); @@ -169,9 +172,11 @@ function _callServer(name: string, args?: any, extraData = {}): Promise { case "client": { const id = util.uid(); return new Promise(resolve => { - glob.__rpcPending[id] = { - resolve - }; + if(!extraData.noRet){ + glob.__rpcPending[id] = { + resolve + }; + } const event: Event = { req: 1, id, @@ -184,7 +189,7 @@ function _callServer(name: string, args?: any, extraData = {}): Promise { }); } case "cef": { - return callClient('__rpc:callServer', [name, args]); + return callClient('__rpc:callServer', [name, args, +extraData.noRet]); } } } @@ -201,7 +206,61 @@ function _callServer(name: string, args?: any, extraData = {}): Promise { */ export function callServer(name: string, args?: any, options: CallOptions = {}): Promise { if(arguments.length < 1 || arguments.length > 3) return util.promiseReject('callServer expects 1 to 3 arguments: "name", optional "args", and optional "options"'); - return util.promiseTimeout(_callServer(name, args, {}), options.timeout); + + let extraData: any = {}; + if(options.noRet) extraData.noRet = 1; + + return util.promiseTimeout(_callServer(name, args, extraData), options.timeout); +} + +function _callClient(player: Player, name: string, args?: any, extraData: any = {}): Promise { + switch(environment){ + case 'client': { + return call(name, args); + } + case 'server': { + const id = util.uid(); + return new Promise(resolve => { + if(!extraData.noRet){ + glob.__rpcPending[id] = { + resolve, + player + }; + } + const event: Event = { + req: 1, + id, + name, + env: environment, + args, + ...extraData + }; + player.call(PROCESS_EVENT, [util.stringifyData(event)]); + }); + } + case 'cef': { + const id = util.uid(); + return glob[IDENTIFIER].then((browserId: string) => { + return new Promise(resolve => { + if(!extraData.noRet){ + glob.__rpcPending[id] = { + resolve + }; + } + const event: Event = { + b: browserId, + req: 1, + id, + name, + env: environment, + args, + ...extraData + }; + mp.trigger(PROCESS_EVENT, util.stringifyData(event)); + }); + }); + } + } } /** @@ -216,72 +275,42 @@ export function callServer(name: string, args?: any, options: CallOptions = {}): * @returns The result from the procedure. */ export function callClient(player: Player | string, name?: string | any, args?: any, options: CallOptions = {}): Promise { - let promise; - switch(environment){ case 'client': { options = args || {}; args = name; name = player; + player = null; if((arguments.length < 1 || arguments.length > 3) || typeof name !== 'string') return util.promiseReject('callClient from the client expects 1 to 3 arguments: "name", optional "args", and optional "options"'); - promise = call(name, args); break; } case 'server': { if((arguments.length < 2 || arguments.length > 4) || typeof player !== 'object') return util.promiseReject('callClient from the server expects 2 to 4 arguments: "player", "name", optional "args", and optional "options"'); - const id = util.uid(); - promise = new Promise(resolve => { - glob.__rpcPending[id] = { - resolve, - player - }; - const event: Event = { - req: 1, - id, - name, - env: environment, - args - }; - player.call(PROCESS_EVENT, [util.stringifyData(event)]); - }); break; } case 'cef': { options = args || {}; args = name; name = player; + player = null; if((arguments.length < 1 || arguments.length > 3) || typeof name !== 'string') return util.promiseReject('callClient from the browser expects 1 to 3 arguments: "name", optional "args", and optional "options"'); - const id = util.uid(); - promise = glob[IDENTIFIER].then((browserId: string) => { - return new Promise(resolve => { - glob.__rpcPending[id] = { - resolve - }; - const event: Event = { - b: browserId, - req: 1, - id, - name, - env: environment, - args - }; - mp.trigger(PROCESS_EVENT, util.stringifyData(event)); - }); - }); break; } } - if(promise){ - return util.promiseTimeout(promise, options.timeout); - } + let extraData: any = {}; + if(options.noRet) extraData.noRet = 1; + + return util.promiseTimeout(_callClient(typeof player === 'object' ? player : null, name, args, extraData), options.timeout); } -function _callBrowser(id: string, browser: Browser, name: string, args?: any, extraData = {}): Promise { +function _callBrowser(id: string, browser: Browser, name: string, args?: any, extraData: any = {}): Promise { return new Promise(resolve => { - glob.__rpcPending[id] = { - resolve - }; + if(!extraData.noRet){ + glob.__rpcPending[id] = { + resolve + }; + } passEventToBrowser(browser, { req: 1, id, @@ -293,7 +322,7 @@ function _callBrowser(id: string, browser: Browser, name: string, args?: any, ex }); } -function _callBrowsers(player: Player, name: string, args?: any, extraData = {}): Promise { +function _callBrowsers(player: Player, name: string, args?: any, extraData: any = {}): Promise { switch(environment){ case 'client': const id = util.uid(); @@ -303,9 +332,9 @@ function _callBrowsers(player: Player, name: string, args?: any, extraData = {}) if(!browser || !util.isBrowserValid(browser)) return util.promiseReject(ERR_NOT_FOUND); return _callBrowser(id, browser, name, args, extraData); case 'server': - return callClient(player, '__rpc:callBrowsers', [name, args]); + return _callClient(player, '__rpc:callBrowsers', [name, args, +extraData.noRet], extraData); case 'cef': - return callClient('__rpc:callBrowsers', [name, args]); + return _callClient(null, '__rpc:callBrowsers', [name, args, +extraData.noRet], extraData); } } @@ -322,6 +351,7 @@ function _callBrowsers(player: Player, name: string, args?: any, extraData = {}) */ export function callBrowsers(player: Player | string, name?: string | any, args?: any, options: CallOptions = {}): Promise { let promise; + let extraData: any = {}; switch(environment){ case 'client': @@ -330,11 +360,13 @@ export function callBrowsers(player: Player | string, name?: string | any, args? args = name; name = player; if(arguments.length < 1 || arguments.length > 3) return util.promiseReject('callBrowsers from the client or browser expects 1 to 3 arguments: "name", optional "args", and optional "options"'); - promise = _callBrowsers(null, name, args, {}); + if(options.noRet) extraData.noRet = 1; + promise = _callBrowsers(null, name, args, extraData); break; case 'server': if(arguments.length < 2 || arguments.length > 4) return util.promiseReject('callBrowsers from the server expects 2 to 4 arguments: "player", "name", optional "args", and optional "options"'); - promise = _callBrowsers(player as Player, name, args, {}); + if(options.noRet) extraData.noRet = 1; + promise = _callBrowsers(player as Player, name, args, extraData); break; } @@ -359,7 +391,10 @@ export function callBrowser(browser: Browser, name: string, args?: any, options: if(arguments.length < 2 || arguments.length > 4) return util.promiseReject('callBrowser expects 2 to 4 arguments: "browser", "name", optional "args", and optional "options"'); const id = util.uid(); - return util.promiseTimeout(_callBrowser(id, browser, name, args, {}), options.timeout); + let extraData: any = {}; + if(options.noRet) extraData.noRet = 1; + + return util.promiseTimeout(_callBrowser(id, browser, name, args, extraData), options.timeout); } export default {