/
rage-rpc.js
1 lines (1 loc) · 13.3 KB
/
rage-rpc.js
1
"use strict";var e;Object.defineProperty(exports,"__esModule",{value:!0}),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"}(e||(e={}));let r=!1;function getEnvironment(){if(mp.joaat)return"server";if(mp.game&&mp.game.joaat)return"client";if(mp.trigger)return"cef";throw new Error("Unknown RAGE environment")}function log(e,t="info"){if(!r)return;const n=getEnvironment(),s=mp.console;(s?mp.console:console)[s?{info:"logInfo",error:"logError",warn:"logWarn"}[t]:"info"===t?"log":t](`RPC (${n}): ${e}`)}function isObjectMpType(r,t){const n="client"===getEnvironment();if(r&&"object"==typeof r&&void 0!==r.id){const validate=(e,t,s)=>n?r.type===e&&t.at(r.id)===r:r instanceof s;switch(t){case e.Blip:return validate("blip",mp.blips,mp.Blip);case e.Checkpoint:return validate("checkpoint",mp.checkpoints,mp.Checkpoint);case e.Colshape:return validate("colshape",mp.colshapes,mp.Colshape);case e.Label:return validate("textlabel",mp.labels,mp.TextLabel);case e.Marker:return validate("marker",mp.markers,mp.Marker);case e.Object:return validate("object",mp.objects,mp.Object);case e.Pickup:return validate("pickup",mp.pickups,mp.Pickup);case e.Player:return validate("player",mp.players,mp.Player);case e.Vehicle:return validate("vehicle",mp.vehicles,mp.Vehicle)}}return!1}function generateId(){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 stringifyData(r){const t=getEnvironment();return JSON.stringify(r,((r,n)=>{if("client"===t||"server"===t&&n&&"object"==typeof n){let r;if(isObjectMpType(n,e.Blip)?r=e.Blip:isObjectMpType(n,e.Checkpoint)?r=e.Checkpoint:isObjectMpType(n,e.Colshape)?r=e.Colshape:isObjectMpType(n,e.Marker)?r=e.Marker:isObjectMpType(n,e.Object)?r=e.Object:isObjectMpType(n,e.Pickup)?r=e.Pickup:isObjectMpType(n,e.Player)?r=e.Player:isObjectMpType(n,e.Vehicle)&&(r=e.Vehicle),r)return{__t:r,i:"number"==typeof n.remoteId?n.remoteId:n.id}}return n}))}function promiseTimeout(e,r){return"number"==typeof r?Promise.race([new Promise(((e,t)=>{setTimeout((()=>t("TIMEOUT")),r)})),e]):e}function isBrowserValid(e){try{e.url}catch(e){return!1}return!0}const t=getEnvironment(),n="cef"===t?window:global;if(n["__rpc:processPartial"]||(n.__rpcPartialData={},n["__rpc:processPartial"]=(e,r,s,o,i)=>{"server"!==t&&(i=o,o=s,s=r,r=e),n.__rpcPartialData[r]||(n.__rpcPartialData[r]=new Array(o)),n.__rpcPartialData[r][s]=i,n.__rpcPartialData[r].includes(void 0)||("server"===t?n["__rpc:process"](e,n.__rpcPartialData[r].join("")):n["__rpc:process"](n.__rpcPartialData[r].join("")),delete n.__rpcPartialData[r])}),!n["__rpc:process"]){if(n.__rpcListeners={},n.__rpcPending={},n.__rpcEvListeners={},n["__rpc:process"]=(r,s)=>{"server"!==t&&(s=r);const o=function parseData(r){const t=getEnvironment();return JSON.parse(r,((r,n)=>{if(("client"===t||"server"===t)&&n&&"object"==typeof n&&"string"==typeof n.__t&&"number"==typeof n.i&&2===Object.keys(n).length){const r=n.i;let s;switch(n.__t){case e.Blip:s=mp.blips;break;case e.Checkpoint:s=mp.checkpoints;break;case e.Colshape:s=mp.colshapes;break;case e.Label:s=mp.labels;break;case e.Marker:s=mp.markers;break;case e.Object:s=mp.objects;break;case e.Pickup:s=mp.pickups;break;case e.Player:s=mp.players;break;case e.Vehicle:s=mp.vehicles}if(s)return s["client"===t?"atRemoteId":"at"](r)}return n}))}(s);if(o.req){const e={id:o.id,environment:o.fenv||o.env};"server"===t&&(e.player=r);const s={ret:1,id:o.id,env:t};let i;switch(t){case"server":i=r=>e.player.call("__rpc:process",[stringifyData(r)]);break;case"client":if("server"===o.env)i=e=>mp.events.callRemote("__rpc:process",stringifyData(e));else if("cef"===o.env){const r=o.b&&n.__rpcBrowsers[o.b];e.browser=r,i=e=>r&&isBrowserValid(r)&&passEventToBrowser(r,e,!0)}break;default:i=e=>mp.trigger("__rpc:process",stringifyData(e))}if(i){const r=callProcedure(o.name,o.args,e);o.noRet||r.then((e=>i({...s,res:e}))).catch((e=>i({...s,err:e||null})))}}else if(o.ret){const e=n.__rpcPending[o.id];if("server"===t&&e.player!==r)return;e&&(e.resolve(o.hasOwnProperty("err")?Promise.reject(o.err):Promise.resolve(o.res)),delete n.__rpcPending[o.id])}},"cef"===t)void 0===n["__rpc:id"]&&(n["__rpc:id"]=new Promise((e=>{window.name?e(window.name):n["__rpc:id:resolve"]=e})));else if(mp.events.add("__rpc:process",n["__rpc:process"]),mp.events.add("__rpc:processPartial",n["__rpc:processPartial"]),"client"===t){register("__rpc:callServer",(([e,r,t],n)=>_callServer(e,r,{fenv:n.environment,noRet:t}))),register("__rpc:callBrowsers",(([e,r,t],n)=>_callBrowsers(null,e,r,{fenv:n.environment,noRet:t}))),n.__rpcBrowsers={};const initBrowser=e=>{const r=generateId();Object.keys(n.__rpcBrowsers).forEach((r=>{const t=n.__rpcBrowsers[r];t&&isBrowserValid(t)&&t!==e||delete n.__rpcBrowsers[r]})),n.__rpcBrowsers[r]=e,e.execute(`\n window.name = '${r}';\n if(typeof window['__rpc:id'] === 'undefined'){\n window['__rpc:id'] = Promise.resolve(window.name);\n }else{\n window['__rpc:id:resolve'](window.name);\n }\n `)};mp.browsers.forEach(initBrowser),mp.events.add("browserCreated",initBrowser),n.__rpcBrowserProcedures={},mp.events.add("__rpc:browserRegister",(e=>{const[r,t]=JSON.parse(e);n.__rpcBrowserProcedures[t]=r})),mp.events.add("__rpc:browserUnregister",(e=>{const[r,t]=JSON.parse(e);n.__rpcBrowserProcedures[t]===r&&delete n.__rpcBrowserProcedures[t]})),register("__rpc:triggerEventBrowsers",(([e,r],t)=>{Object.keys(n.__rpcBrowsers).forEach((s=>{const o=n.__rpcBrowsers[s];o&&isBrowserValid(o)?_callBrowser(o,"__rpc:triggerEvent",[e,r],{fenv:t.environment,noRet:1}):delete n.__rpcBrowsers[s]}))}))}register("__rpc:triggerEvent",(([e,r],t)=>callEvent(e,r,t)))}function passEventToBrowser(e,r,t){const n=stringifyData(r);e.execute(`var process = window["__rpc:process"]; if(process){ process(${JSON.stringify(n)}); }else{ ${t?"":`mp.trigger("__rpc:process", '{"ret":1,"id":"${r.id}","err":"PROCEDURE_NOT_FOUND","env":"cef"}');`} }`)}function callProcedure(e,r,t){const s=n.__rpcListeners[e];return s?Promise.resolve(s(r,t)):Promise.reject(`PROCEDURE_NOT_FOUND (${e})`)}function sendEventData(e,r){const t={client:(e,...r)=>mp.events.callRemote(e,...r),server:(e,...t)=>r.call(e,[...t])},n=e.env,s=stringifyData(e);if(s.length>32e3){const r=function chunkSubstr(e,r){const t=Math.ceil(e.length/r),n=new Array(t);let s=0;for(let o=0;o<t;o+=1)n[o]=e.substring(s,r),s+=r;return n}(s,32e3);r.forEach(((s,o)=>{t[n]("__rpc:processPartial",e.id,o,r.length,s)}))}else t[n]("__rpc:process",s)}function register(e,r){if("string"!=typeof e||!r||"function"!=typeof r)throw new Error(`register expects 2 arguments: "name" and "cb" - ("${e}")`);return log(`Registered procedure "${e}"`),"cef"===t&&n["__rpc:id"].then((r=>mp.trigger("__rpc:browserRegister",JSON.stringify([r,e])))),n.__rpcListeners[e]=r,()=>unregister(e)}function unregister(e){if("string"!=typeof e)throw new Error(`unregister expects 1 argument: "name" - ("${e}")`);log(`Unregistered procedure "${e}"`),"cef"===t&&n["__rpc:id"].then((r=>mp.trigger("__rpc:browserUnregister",JSON.stringify([r,e])))),n.__rpcListeners[e]=void 0}function call(e,r,n={}){return"string"!=typeof e?Promise.reject(`call expects 1 to 3 arguments: "name", optional "args", and optional "options" - ("${e}")`):promiseTimeout(callProcedure(e,r,{environment:t}),n.timeout)}function _callServer(e,r,s={}){switch(t){case"server":return call(e,r);case"client":{const o=generateId();return new Promise((i=>{s.noRet||(n.__rpcPending[o]={resolve:i});sendEventData({req:1,id:o,name:e,env:t,args:r,...s})}))}case"cef":return callClient("__rpc:callServer",[e,r,Number(s.noRet)])}}function _callClient(e,r,s,o={}){switch(t){case"client":return call(r,s);case"server":{const i=generateId();return new Promise((c=>{o.noRet||(n.__rpcPending[i]={resolve:c,player:e});sendEventData({req:1,id:i,name:r,env:t,args:s,...o},e)}))}case"cef":{const e=generateId();return n["__rpc:id"].then((i=>new Promise((c=>{o.noRet||(n.__rpcPending[e]={resolve:c});const a={b:i,req:1,id:e,name:r,env:t,args:s,...o};mp.trigger("__rpc:process",stringifyData(a))}))))}}}function callClient(e,r,n,s={}){switch(t){case"client":if(s=n||{},n=r,r=e,e=null,"string"!=typeof r)return Promise.reject(`callClient from the client expects 1 to 3 arguments: "name", optional "args", and optional "options" - ("${r}")`);break;case"server":if("string"!=typeof r||"object"!=typeof e)return Promise.reject(`callClient from the server expects 2 to 4 arguments: "player", "name", optional "args", and optional "options" - ("${r}")`);break;case"cef":if(s=n||{},n=r,r=e,e=null,"string"!=typeof r)return Promise.reject(`callClient from the browser expects 1 to 3 arguments: "name", optional "args", and optional "options" - ("${r}")`)}const o={};return s.noRet&&(o.noRet=1),promiseTimeout(_callClient(e,r,n,o),s.timeout)}function _callBrowser(e,r,s,o={}){return new Promise((i=>{const c=generateId();o.noRet||(n.__rpcPending[c]={resolve:i}),passEventToBrowser(e,{req:1,id:c,name:r,env:t,args:s,...o},!1)}))}function _callBrowsers(e,r,s,o={}){switch(t){case"client":{const e=n.__rpcBrowserProcedures[r];if(!e)return Promise.reject(`PROCEDURE_NOT_FOUND (${r})`);const t=n.__rpcBrowsers[e];return t&&isBrowserValid(t)?_callBrowser(t,r,s,o):Promise.reject(`PROCEDURE_NOT_FOUND (${r})`)}case"server":return _callClient(e,"__rpc:callBrowsers",[r,s,Number(o.noRet)],o);case"cef":return _callClient(null,"__rpc:callBrowsers",[r,s,Number(o.noRet)],o)}}function callEvent(e,r,t){const s=n.__rpcEvListeners[e];s&&s.forEach((e=>e(r,t)))}function off(e,r){if("string"!=typeof e||!r||"function"!=typeof r)throw new Error(`off expects 2 arguments: "name" and "cb" - ("${e}")`);const t=n.__rpcEvListeners[e];t&&(log(`Unregistered procedure listener "${e}"`),t.delete(r))}exports.call=call,exports.callBrowser=function callBrowser(e,r,n,s={}){if("client"!==t)return Promise.reject(`callBrowser can only be used in the client environment - ("${r}")`);if(!isBrowserValid(e)||"string"!=typeof r)return Promise.reject(`callBrowser expects 2 to 4 arguments: "browser", "name", optional "args", and optional "options" - ("${r}")`);const o={};return s.noRet&&(o.noRet=1),promiseTimeout(_callBrowser(e,r,n,o),s.timeout)},exports.callBrowsers=function callBrowsers(e,r,n,s={}){let o;const i={};switch(t){case"client":case"cef":if(s=n||{},n=r,"string"!=typeof(r=e))return Promise.reject(`callBrowsers from the client or browser expects 1 to 3 arguments: "name", optional "args", and optional "options" - ("${r}")`);s.noRet&&(i.noRet=1),o=_callBrowsers(null,r,n,i);break;case"server":if("string"!=typeof r||"object"!=typeof e)return Promise.reject(`callBrowsers from the server expects 2 to 4 arguments: "player", "name", optional "args", and optional "options" - ("${r}")`);s.noRet&&(i.noRet=1),o=_callBrowsers(e,r,n,i)}if(o)return promiseTimeout(o,s.timeout)},exports.callClient=callClient,exports.callServer=function callServer(e,r,t={}){if("string"!=typeof e)return Promise.reject(`callServer expects 1 to 3 arguments: "name", optional "args", and optional "options" - ("${e}")`);const n={};return t.noRet&&(n.noRet=1),promiseTimeout(_callServer(e,r,n),t.timeout)},exports.off=off,exports.on=function on(e,r){if("string"!=typeof e||!r||"function"!=typeof r)throw new Error(`on expects 2 arguments: "name" and "cb" - ("${e}")`);log(`Registered procedure listener "${e}"`);const t=n.__rpcEvListeners[e]||new Set;return t.add(r),n.__rpcEvListeners[e]=t,()=>off(e,r)},exports.register=register,exports.setDebugMode=function setDebugMode(e){r=e},exports.trigger=function trigger(e,r){if("string"!=typeof e)throw new Error(`trigger expects 1 or 2 arguments: "name", and optional "args" - ("${e}")`);callEvent(e,r,{environment:t})},exports.triggerBrowser=function triggerBrowser(e,r,n){if("client"!==t)throw new Error(`callBrowser can only be used in the client environment - ("${r}")`);if(!isBrowserValid(e)||"string"!=typeof r)throw new Error(`callBrowser expects 2 or 3 arguments: "browser", "name", and optional "args" - ("${r}")`);_callBrowser(e,"__rpc:triggerEvent",[r,n],{noRet:1})},exports.triggerBrowsers=function triggerBrowsers(e,r,n){switch(t){case"client":case"cef":if(n=r,r=e,e=null,"string"!=typeof r)throw new Error(`triggerBrowsers from the client or browser expects 1 or 2 arguments: "name", and optional "args" - ("${r}")`);break;case"server":if("string"!=typeof r||"object"!=typeof e)throw new Error(`triggerBrowsers from the server expects 2 or 3 arguments: "player", "name", and optional "args" - ("${r}")`)}_callClient(e,"__rpc:triggerEventBrowsers",[r,n],{noRet:1})},exports.triggerClient=function triggerClient(e,r,n){switch(t){case"client":if(n=r,r=e,e=null,"string"!=typeof r)throw new Error(`triggerClient from the client expects 1 or 2 arguments: "name", and optional "args" - ("${r}")`);break;case"server":if("string"!=typeof r||"object"!=typeof e)throw new Error(`triggerClient from the server expects 2 or 3 arguments: "player", "name", and optional "args" - ("${r}")`);break;case"cef":if(n=r,r=e,e=null,"string"!=typeof r)throw new Error(`triggerClient from the browser expects 1 or 2 arguments: "name", and optional "args" - ("${r}")`)}_callClient(e,"__rpc:triggerEvent",[r,n],{noRet:1})},exports.triggerServer=function triggerServer(e,r){if("string"!=typeof e)throw new Error(`triggerServer expects 1 or 2 arguments: "name", and optional "args" - ("${e}")`);_callServer("__rpc:triggerEvent",[e,r],{noRet:1})},exports.unregister=unregister,exports.version="0.2.5";