rustplus-ts
Version:
Rust+ API Wrapper written in TypeScript for the game Rust.
1,016 lines (1,011 loc) • 94.8 kB
JavaScript
/*
Copyright (C) 2025 Alexander Emanuelsson (alexemanuelol)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
https://github.com/alexemanuelol/rustplus-ts
*/
'use strict';
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RustPlus = exports.ConsumeTokensError = exports.AppResponseError = exports.EmitErrorType = void 0;
const ws_1 = __importDefault(require("ws"));
const events_1 = require("events");
const rpi = __importStar(require("./interfaces/rustplus"));
const validation = __importStar(require("./validation"));
var EmitErrorType;
(function (EmitErrorType) {
EmitErrorType[EmitErrorType["WebSocket"] = 0] = "WebSocket";
EmitErrorType[EmitErrorType["Callback"] = 1] = "Callback";
})(EmitErrorType || (exports.EmitErrorType = EmitErrorType = {}));
var AppResponseError;
(function (AppResponseError) {
/**
* No error was found.
*/
AppResponseError[AppResponseError["NoError"] = 0] = "NoError";
/**
* unknown occurences:
* - unknown
*/
AppResponseError[AppResponseError["Unknown"] = 1] = "Unknown";
/**
* server_error occurences:
* - If there was an error during the executing of request handler on server side.
* - If CameraRendererManager instance is null.
*/
AppResponseError[AppResponseError["ServerError"] = 2] = "ServerError";
/**
* banned occurences:
* - Trying to run any request while being Rust+ banned on the rust server.
*/
AppResponseError[AppResponseError["Banned"] = 3] = "Banned";
/**
* rate_limit occurences:
* - Too many requests too fast, tokens ran out.
*/
AppResponseError[AppResponseError["RateLimit"] = 4] = "RateLimit";
/**
* not_found occurences:
* - playerToken might be invalid, rust server might have reset Rust+ data.
* - smart device can't be found.
* - Trying to run promoteToLeader on someone that is not in the team.
* - Trying to run cameraSubscribe on a cameraId that could not be found.
*/
AppResponseError[AppResponseError["NotFound"] = 5] = "NotFound";
/**
* wrong_type occurences:
* - Trying to run setEntityValue on Alarm or StorageMonitor.
* - Trying to run checkSubscription on Switch or StorageMonitor.
* - Trying to run setSubscription on Switch or StorageMonitor.
*/
AppResponseError[AppResponseError["WrongType"] = 6] = "WrongType";
/**
* no_team occurences:
* - Trying to run promoteToLeader when you're not in a team.
* - Trying to run getTeamChat when you're not in a team.
*/
AppResponseError[AppResponseError["NoTeam"] = 7] = "NoTeam";
/**
* no_clan occurences:
* - Trying to run getClanInfo when you're not in a clan.
* - Trying to run setClanMotd when you're not in a clan.
* - Trying to run getClanChat when you're not in a clan.
* - Trying to run sendClanMessage when you're not in a clan.
*/
AppResponseError[AppResponseError["NoClan"] = 8] = "NoClan";
/**
* no_map occurences:
* - Trying to run getMap but imageData is null.
*/
AppResponseError[AppResponseError["NoMap"] = 9] = "NoMap";
/**
* no_camera occurences:
* - Trying to run cameraInput when there is no camera subscribed to.
*/
AppResponseError[AppResponseError["NoCamera"] = 10] = "NoCamera";
/**
* no_player occurences:
* - Trying to run cameraSubscribe while player token is invalid or player caller dead.
*/
AppResponseError[AppResponseError["NoPlayer"] = 11] = "NoPlayer";
/**
* access_denied occurences:
* - Trying to run cameraSubscribe with a cameraId but access was denied.
* - Trying to run getNexusAuth but access was denied.
* - Trying to run promoteToLeader when you're not the leader.
*/
AppResponseError[AppResponseError["AccessDenied"] = 12] = "AccessDenied";
/**
* player_online occurences:
* - Trying to run cameraSubscribe when requester online.
*/
AppResponseError[AppResponseError["PlayerOnline"] = 13] = "PlayerOnline";
/**
* invalid_playerid occurences:
* - Trying to run getNexusAuth but playerid is invalid.
*/
AppResponseError[AppResponseError["InvalidPlayerid"] = 14] = "InvalidPlayerid";
/**
* invalid_id occurences:
* - Trying to run cameraSubscribe with a cameraId that is an empty string.
*/
AppResponseError[AppResponseError["InvalidId"] = 15] = "InvalidId";
/**
* invalid_motd occurences:
* - Trying to run setClanMotd but motd was invalid.
*/
AppResponseError[AppResponseError["InvalidMotd"] = 16] = "InvalidMotd";
/**
* too_many_subscribers occurences:
* - Trying to run setSubscription on a Alarm that have too many subscribers already.
*/
AppResponseError[AppResponseError["TooManySubscribers"] = 17] = "TooManySubscribers";
/**
* not_enabled occurences:
* - Trying to run cameraInput when cameras are disabled on the rust server.
* - Trying to run cameraSubscribe when cameras are disabled on the rust server.
* - Trying to run cameraUnsubscribe when cameras are disabled on the rust server.
*/
AppResponseError[AppResponseError["NotEnabled"] = 18] = "NotEnabled";
/**
* message_not_sent occurences:
* - Trying to run sendClanMessage but something went wrong on server side.
* - Trying to run sendTeamMessage but something went wrong on server side.
*/
AppResponseError[AppResponseError["MessageNotSent"] = 19] = "MessageNotSent";
})(AppResponseError || (exports.AppResponseError = AppResponseError = {}));
var ConsumeTokensError;
(function (ConsumeTokensError) {
ConsumeTokensError[ConsumeTokensError["NoError"] = 0] = "NoError";
ConsumeTokensError[ConsumeTokensError["Unknown"] = 1] = "Unknown";
ConsumeTokensError[ConsumeTokensError["NotEnoughConnectionTokens"] = 2] = "NotEnoughConnectionTokens";
ConsumeTokensError[ConsumeTokensError["NotEnoughPlayerIdTokens"] = 3] = "NotEnoughPlayerIdTokens";
ConsumeTokensError[ConsumeTokensError["WaitReplenishTimeout"] = 4] = "WaitReplenishTimeout";
})(ConsumeTokensError || (exports.ConsumeTokensError = ConsumeTokensError = {}));
function getAddress(useFacepunchProxy, ip, port) {
return useFacepunchProxy ? `wss://companion-rust.facepunch.com/game/${ip}/${port}` : `ws://${ip}:${port}`;
}
class RustPlus extends events_1.EventEmitter {
static MAX_REQUESTS_PER_IP_ADDRESS = 50;
static REQUESTS_PER_IP_REPLENISH_RATE = 15; /* Tokens per second. */
static MAX_REQUESTS_PER_PLAYER_ID = 25;
static REQUESTS_PER_PLAYER_ID_REPLENISH_RATE = 3; /* Tokens per second. */
static MAX_REQUESTS_FOR_SERVER_PAIRING = 5;
static REQUESTS_FOR_SERVER_PAIRING_REPLENISH_RATE = 0.1; /* Tokens per second. */
static REQUEST_GET_INFO_TOKEN_COST = 1;
static REQUEST_GET_TIME_TOKEN_COST = 1;
static REQUEST_GET_MAP_TOKEN_COST = 5;
static REQUEST_GET_TEAM_INFO_TOKEN_COST = 1;
static REQUEST_GET_TEAM_CHAT_TOKEN_COST = 1;
static REQUEST_SEND_TEAM_MESSAGE_TOKEN_COST = 2;
static REQUEST_GET_ENTITY_INFO_TOKEN_COST = 1;
static REQUEST_SET_ENTITY_VALUE_TOKEN_COST = 1;
static REQUEST_CHECK_SUBSCRIPTION_TOKEN_COST = 1;
static REQUEST_SET_SUBSCRIPTION_TOKEN_COST = 1;
static REQUEST_GET_MAP_MARKERS_TOKEN_COST = 1;
static REQUEST_PROMOTE_TO_LEADER_TOKEN_COST = 1;
static REQUEST_GET_CLAN_INFO_TOKEN_COST = 1;
static REQUEST_SET_CLAN_MOTD_TOKEN_COST = 1;
static REQUEST_GET_CLAN_CHAT_TOKEN_COST = 1;
static REQUEST_SEND_CLAN_MESSAGE_TOKEN_COST = 2;
static REQUEST_GET_NEXUS_AUTH_TOKEN_COST = 1;
static REQUEST_CAMERA_SUBSCRIBE_TOKEN_COST = 1;
static REQUEST_CAMERA_UNSUBSCRIBE_TOKEN_COST = 1;
static REQUEST_CAMERA_INPUT_TOKEN_COST = 0.01;
static REQUEST_GET_INFO_TIMEOUT_MS = 10000;
static REQUEST_GET_TIME_TIMEOUT_MS = 10000;
static REQUEST_GET_MAP_TIMEOUT_MS = 30000;
static REQUEST_GET_TEAM_INFO_TIMEOUT_MS = 10000;
static REQUEST_GET_TEAM_CHAT_TIMEOUT_MS = 10000;
static REQUEST_SEND_TEAM_MESSAGE_TIMEOUT_MS = 10000;
static REQUEST_GET_ENTITY_INFO_TIMEOUT_MS = 10000;
static REQUEST_SET_ENTITY_VALUE_TIMEOUT_MS = 10000;
static REQUEST_CHECK_SUBSCRIPTION_TIMEOUT_MS = 10000;
static REQUEST_SET_SUBSCRIPTION_TIMEOUT_MS = 10000;
static REQUEST_GET_MAP_MARKERS_TIMEOUT_MS = 10000;
static REQUEST_PROMOTE_TO_LEADER_TIMEOUT_MS = 10000;
static REQUEST_GET_CLAN_INFO_TIMEOUT_MS = 10000;
static REQUEST_SET_CLAN_MOTD_TIMEOUT_MS = 10000;
static REQUEST_GET_CLAN_CHAT_TIMEOUT_MS = 10000;
static REQUEST_SEND_CLAN_MESSAGE_TIMEOUT_MS = 10000;
static REQUEST_GET_NEXUS_AUTH_TIMEOUT_MS = 10000;
static REQUEST_CAMERA_SUBSCRIBE_TIMEOUT_MS = 10000;
static REQUEST_CAMERA_UNSUBSCRIBE_TIMEOUT_MS = 10000;
static REQUEST_CAMERA_INPUT_TIMEOUT_MS = 10000;
ip;
port;
useFacepunchProxy;
logger;
seq;
seqCallbacks;
ws;
tokens;
replenishInterval;
/**
* @param {string} ip The ip address or hostname of the Rust Server.
* @param {string} port The port of the Rust Server (app.port in server.cfg)
* @param useFacepunchProxy True to use secure websocket via Facepunch's proxy, or false to directly connect
* to Rust Server.
*
* Events emitted by the RustPlus class instance
* - connecting: When we are connecting to the Rust Server.
* - connected: When we are connected to the Rust Server.
* - message: When an AppMessage has been received from the Rust Server.
* - request: When an AppRequest has been sent to the Rust Server.
* - disconnected: When we are disconnected from the Rust Server.
* - error: When something goes wrong with the WebSocket, incoming message or the request callback function.
*/
constructor(ip, port, useFacepunchProxy = false, logger = null) {
super();
this.ip = ip;
this.port = port;
this.useFacepunchProxy = useFacepunchProxy;
this.logger = logger;
this.seq = 0;
this.seqCallbacks = [];
this.ws = null;
this.tokens = {
connection: RustPlus.MAX_REQUESTS_PER_IP_ADDRESS,
playerId: {},
serverPairing: RustPlus.MAX_REQUESTS_FOR_SERVER_PAIRING
};
this.replenishInterval = null;
}
/**
* Function that replenish the connection, playerId and server pairing tokens.
*/
replenishTask() {
this.replenishConnectionTokens();
this.replenishPlayerIdTokens();
this.replenishServerPairingTokens();
}
/**
* Function that replenish the connection tokens.
*/
replenishConnectionTokens() {
/* Replenish tokens for requests per ip. */
if (this.tokens.connection < RustPlus.MAX_REQUESTS_PER_IP_ADDRESS) {
this.tokens.connection = Math.min(this.tokens.connection + RustPlus.REQUESTS_PER_IP_REPLENISH_RATE, RustPlus.MAX_REQUESTS_PER_IP_ADDRESS);
}
}
/**
* Function that replenish the playerId tokens.
*/
replenishPlayerIdTokens() {
/* Replenish tokens for requests per player id. */
for (const playerId in this.tokens.playerId) {
if (this.tokens.playerId[playerId] < RustPlus.MAX_REQUESTS_PER_PLAYER_ID) {
this.tokens.playerId[playerId] = Math.min(this.tokens.playerId[playerId] + RustPlus.REQUESTS_PER_PLAYER_ID_REPLENISH_RATE, RustPlus.MAX_REQUESTS_PER_PLAYER_ID);
}
}
}
/**
* Function that replenish the server pairing tokens.
*/
replenishServerPairingTokens() {
/* Replenish tokens for requests for server pairing. */
if (this.tokens.serverPairing < RustPlus.MAX_REQUESTS_FOR_SERVER_PAIRING) {
this.tokens.serverPairing = Math.min(this.tokens.serverPairing + RustPlus.REQUESTS_FOR_SERVER_PAIRING_REPLENISH_RATE, RustPlus.MAX_REQUESTS_FOR_SERVER_PAIRING);
}
}
/**
* Consume tokens amount of tokens from connection and playerId.
* @param {string} playerId - The steamId of the player consuming the tokens.
* @param {number} tokens - The tokens to consume.
* @param {boolean} waitForReplenish - If true, it will wait till there are available tokens to consume.
* @param {number} timeoutMs - Timeout if tokens were not replenished in timeout milliseconds.
* @returns {Promise<ConsumeTokensError>} Resolves with a `ConsumeTokensError` enum value indicating success or
* the type of error encountered.
*/
async consumeTokens(playerId, tokens, waitForReplenish, timeoutMs = 10000) {
/* Check if playerId exists, if not, initialize with max tokens. */
if (!(playerId in this.tokens.playerId)) {
this.tokens.playerId[playerId] = RustPlus.MAX_REQUESTS_PER_PLAYER_ID;
}
const startTime = Date.now();
/* Function to check whether there are enough tokens available from connection and playerId. */
const hasEnoughTokens = () => {
return this.tokens.connection >= tokens && this.tokens.playerId[playerId] >= tokens;
};
if (!waitForReplenish && !hasEnoughTokens()) {
if (this.tokens.connection >= tokens) {
return ConsumeTokensError.NotEnoughConnectionTokens;
}
else if (this.tokens.playerId[playerId] >= tokens) {
return ConsumeTokensError.NotEnoughPlayerIdTokens;
}
else {
return ConsumeTokensError.Unknown;
}
}
/* Wait until there are enough tokens or the timeout is reached */
while (!hasEnoughTokens()) {
const elapsedTime = Date.now() - startTime;
if (elapsedTime >= timeoutMs) {
return ConsumeTokensError.WaitReplenishTimeout;
}
await this.delay(100);
}
this.tokens.connection -= tokens;
this.tokens.playerId[playerId] -= tokens;
return ConsumeTokensError.NoError;
}
/**
* Delays the execution of the next operation by a specified number of milliseconds.
*
* @param {number} ms - The amount of time, in milliseconds, to delay the execution.
*
* @returns {Promise<void>} A promise that resolves after the specified delay.
*/
delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Retrieves the next available sequence number for a request.
*
* Increments the sequence number and ensures that it is unique by checking for any existing callbacks
* associated with the current sequence number. If a callback exists, it continues to increment the
* sequence until a unique number is found.
*
* @returns {number} The next available sequence number.
*/
getNextSeq() {
let nextSeq = this.seq + 1;
/* Find the next available sequence number. */
while (this.seqCallbacks[nextSeq]) {
nextSeq++;
}
this.seq = nextSeq;
return nextSeq;
}
/**
* Setup and connect to the Rust Server via WebSocket.
* @returns {Promise<boolean>} Promise of True if successful, else false.
*/
async connect() {
/* Make sure existing connection is closed before connecting again. */
if (this.ws !== null) {
this.disconnect();
}
this.emit('connecting');
this.ws = new ws_1.default(getAddress(this.useFacepunchProxy, this.ip, this.port));
this.ws.on('open', () => { this.emit('connected'); });
this.ws.on('close', () => { this.emit('disconnected'); });
this.ws.on('error', (e) => { this.emit('error', EmitErrorType.WebSocket, e); });
this.ws.on('message', (data) => {
try {
if (!data) {
throw new Error('Received empty or invalid message data.');
}
let handled = false;
const appMessage = rpi.AppMessage.fromBinary(data);
if (appMessage.response && this.seqCallbacks[appMessage.response.seq]) {
const callback = this.seqCallbacks[appMessage.response.seq];
try {
callback(appMessage);
handled = true;
}
catch (callbackError) {
const errorMessage = callbackError instanceof Error ? callbackError.message : 'Unknown error';
this.emit('error', EmitErrorType.Callback, new Error(`ERROR on.message: ${errorMessage}`));
}
finally {
delete this.seqCallbacks[appMessage.response.seq];
}
}
this.emit('message', appMessage, handled);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
this.emit('error', EmitErrorType.Callback, new Error(`ERROR on.message: ${errorMessage}`));
}
});
/* Start interval to replenish tokens every second. */
this.replenishInterval = setInterval(() => this.replenishTask(), 1000);
return true;
}
/**
* Disconnect from the Rust Server and clear WebSocket variable.
* @returns {boolean} True if successful, else false.
*/
async disconnect() {
if (this.replenishInterval) {
clearInterval(this.replenishInterval);
}
if (this.ws !== null) {
this.ws.removeAllListeners();
this.ws.on('error', (error) => { });
try {
this.ws.terminate();
}
catch (error) {
/* Do nothing */
}
this.ws = null;
return true;
}
else {
return false;
}
}
/**
* Check if RustPlus is connected to the server.
* @returns {boolean} True if connected, else false.
*/
isConnected() {
return this.ws !== null && this.ws.readyState === ws_1.default.OPEN;
}
/**
* Sends a request to the Rust server with a specified callback that will be executed upon receiving a response.
* The request is created using the `AppRequest` protocol, and it ensures that the WebSocket connection is open
* before sending the request. The function also handles the sequence number for requests and stores the callback
* for when the response arrives.
*
* @param {Omit<rpi.AppRequest, 'seq' | 'playerId' | 'playerToken'>} data - The data for the request,
* excluding the `seq`, `playerId`,
* and `playerToken`, which are
* provided separately.
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {CallbackFunction} callback - The callback function that will be executed when the server responds.
* @param {number | null} [seq=null] - The sequence number for the request. If not provided, a new sequence number
* is generated.
*
* @returns {Error | void} Returns an `Error` if there was an issue sending the request or formatting the data.
* Returns `void` if the request is successfully sent.
*/
sendRequest(data, playerId, playerToken, callback, seq = null) {
/* Is the WebSocket present? */
if (this.ws === null || this.ws.readyState !== ws_1.default.OPEN) {
return new Error('ERROR sendRequest: WebSocket is not open.');
}
if (seq === null) {
seq = this.getNextSeq();
}
/* Save callback function. */
this.seqCallbacks[seq] = callback;
/* Create AppRequest object. */
let appRequestData;
try {
appRequestData = {
seq: seq,
playerId: playerId,
playerToken: playerToken,
...data
};
if (!validation.isValidAppRequest(appRequestData, this.logger)) {
throw new Error('AppRequest data is invalid.');
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
delete this.seqCallbacks[seq];
return new Error(`ERROR sendRequest: ${errorMessage}`);
}
/* Convert AppRequest object to binary format. */
let appRequest;
try {
appRequest = rpi.AppRequest.toBinary(appRequestData);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
delete this.seqCallbacks[seq];
return new Error(`ERROR sendRequest AppRequest.toBinary: ${errorMessage}`);
}
/* Send AppRequest packet to the rust server. */
try {
this.ws.send(appRequest);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
delete this.seqCallbacks[seq];
return new Error(`ERROR sendRequest ws.send: ${errorMessage}`);
}
this.emit('request', appRequestData);
}
/**
* Sends an asynchronous request to the Rust server and returns a Promise that resolves when a response is received
* or rejects when a timeout is reached. The request is formatted using the `AppRequest` protocol, and the server's
* response is handled within the promise. If no response is received within the provided timeout, an error is
* returned.
*
* @param {Omit<rpi.AppRequest, 'seq' | 'playerId' | 'playerToken'>} data - The data for the request,
* excluding the `seq`, `playerId`,
* and `playerToken`, which are
* passed separately.
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {number} [timeoutMs=10000] - The timeout in milliseconds to wait for a response before returning an error.
*
* @returns {Promise<rpi.AppResponse | Error>} A Promise that resolves to the server's response if
* successful, or an Error if the request times out or encounters
* an issue.
*/
sendRequestAsync(data, playerId, playerToken, timeoutMs = 10000) {
return new Promise((resolve) => {
const seq = this.getNextSeq();
const timeout = setTimeout(() => {
delete this.seqCallbacks[seq];
resolve(new Error('Timeout reached while waiting for response.'));
}, timeoutMs);
const result = this.sendRequest(data, playerId, playerToken, (appMessage) => {
clearTimeout(timeout);
try {
if (!validation.isValidAppMessage(appMessage, this.logger)) {
throw new Error('appMessage is invalid format.');
}
if (!appMessage.response) {
throw new Error('appMessage is missing response.');
}
const response = appMessage.response;
if (response.error) {
resolve(response);
}
else {
resolve(response);
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
resolve(new Error(`ERROR sendRequestAsync: ${errorMessage}`));
}
}, seq);
if (result instanceof Error) {
clearTimeout(timeout);
resolve(result);
}
});
}
/**
* Translates an `AppResponse` error object into a corresponding `AppResponseError` enum value.
* If the `appResponse` contains no error, it returns `AppResponseError.NoError`.
* If the `appResponse.error` matches any known error string, the function maps it to the appropriate
* `AppResponseError` enum. If no matching error string is found, it returns `AppResponseError.Unknown`.
*
* @param {rpi.AppResponse} appResponse - The response object from the Rust server which may contain an error.
*
* @returns {AppResponseError} The corresponding `AppResponseError` enum value based on the error string in the
* `appResponse.error` object. Returns `AppResponseError.NoError` if no error is
* present.
*/
getAppResponseError(appResponse) {
if (!appResponse.error) {
return AppResponseError.NoError;
}
switch (appResponse.error.error) {
case 'server_error': {
return AppResponseError.ServerError;
}
case 'banned': {
return AppResponseError.Banned;
}
case 'rate_limit': {
return AppResponseError.RateLimit;
}
case 'not_found': {
return AppResponseError.NotFound;
}
case 'wrong_type': {
return AppResponseError.WrongType;
}
case 'no_team': {
return AppResponseError.NoTeam;
}
case 'no_clan': {
return AppResponseError.NoClan;
}
case 'no_map': {
return AppResponseError.NoMap;
}
case 'no_camera': {
return AppResponseError.NoCamera;
}
case 'no_player': {
return AppResponseError.NoPlayer;
}
case 'access_denied': {
return AppResponseError.AccessDenied;
}
case 'player_online': {
return AppResponseError.PlayerOnline;
}
case 'invalid_playerid': {
return AppResponseError.InvalidPlayerid;
}
case 'invalid_id': {
return AppResponseError.InvalidId;
}
case 'invalid_motd': {
return AppResponseError.InvalidMotd;
}
case 'too_many_subscribers': {
return AppResponseError.TooManySubscribers;
}
case 'not_enabled': {
return AppResponseError.NotEnabled;
}
case 'message_not_sent': {
return AppResponseError.MessageNotSent;
}
default: {
return AppResponseError.Unknown;
}
}
}
/**
* Rust+ API requests.
*/
/**
* Get the server info (callback version).
* Consumes tokens and then sends a request to retrieve server information.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {CallbackFunction} callback - The callback function that will be executed when a response is received.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
*
* @returns {Promise<ConsumeTokensError | Error | void>} Returns an error if token consumption fails or if there is
* an issue sending the request, otherwise returns void.
*/
async getInfo(playerId, playerToken, callback, waitForReplenish = true) {
const tokenCost = RustPlus.REQUEST_GET_INFO_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
return this.sendRequest({
getInfo: {}
}, playerId, playerToken, callback);
}
/**
* Get the server info (async version).
* Consumes tokens and then sends a request to retrieve server information, returning a promise.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
* @param {number} [timeoutMs=10000] - Time (in milliseconds) to wait for a response before timing out.
*
* @returns {Promise<ConsumeTokensError | Error | rpi.AppResponse>} Returns a promise that resolves to the
* server info (AppResponse), or an error if
* token consumption fails or there is an
* issue with the request.
*/
async getInfoAsync(playerId, playerToken, waitForReplenish = true, timeoutMs = RustPlus.REQUEST_GET_INFO_TIMEOUT_MS) {
const tokenCost = RustPlus.REQUEST_GET_INFO_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
const appResponse = await this.sendRequestAsync({
getInfo: {}
}, playerId, playerToken, timeoutMs);
if (validation.isValidAppResponse(appResponse)) {
return appResponse;
}
else {
return appResponse;
}
}
/**
* Get the server time (callback version).
* Consumes tokens and then sends a request to retrieve server time.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {CallbackFunction} callback - The callback function that will be executed when a response is received.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
*
* @returns {Promise<ConsumeTokensError | Error | void>} Returns an error if token consumption fails or if there is
* an issue sending the request, otherwise returns void.
*/
async getTime(playerId, playerToken, callback, waitForReplenish = true) {
const tokenCost = RustPlus.REQUEST_GET_TIME_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
return this.sendRequest({
getTime: {}
}, playerId, playerToken, callback);
}
/**
* Get the server time (async version).
* Consumes tokens and then sends a request to retrieve server time, returning a promise.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
* @param {number} [timeoutMs=10000] - Time (in milliseconds) to wait for a response before timing out.
*
* @returns {Promise<ConsumeTokensError | Error | rpi.AppResponse>} Returns a promise that resolves to the
* server time (AppResponse), or an error if
* token consumption fails or there is an
* issue with the request.
*/
async getTimeAsync(playerId, playerToken, waitForReplenish = true, timeoutMs = RustPlus.REQUEST_GET_TIME_TIMEOUT_MS) {
const tokenCost = RustPlus.REQUEST_GET_TIME_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
const appResponse = await this.sendRequestAsync({
getTime: {}
}, playerId, playerToken, timeoutMs);
if (validation.isValidAppResponse(appResponse)) {
return appResponse;
}
else {
return appResponse;
}
}
/**
* Get the server map (callback version).
* Consumes tokens and then sends a request to retrieve server map.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {CallbackFunction} callback - The callback function that will be executed when a response is received.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
*
* @returns {Promise<ConsumeTokensError | Error | void>} Returns an error if token consumption fails or if there is
* an issue sending the request, otherwise returns void.
*/
async getMap(playerId, playerToken, callback, waitForReplenish = true) {
const tokenCost = RustPlus.REQUEST_GET_MAP_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
return this.sendRequest({
getMap: {}
}, playerId, playerToken, callback);
}
/**
* Get the server map (async version).
* Consumes tokens and then sends a request to retrieve server map, returning a promise.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
* @param {number} [timeoutMs=10000] - Time (in milliseconds) to wait for a response before timing out.
*
* @returns {Promise<ConsumeTokensError | Error | rpi.AppResponse>} Returns a promise that resolves to the
* server map (AppResponse), or an error if
* token consumption fails or there is an
* issue with the request.
*/
async getMapAsync(playerId, playerToken, waitForReplenish = true, timeoutMs = RustPlus.REQUEST_GET_MAP_TIMEOUT_MS) {
const tokenCost = RustPlus.REQUEST_GET_MAP_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
const appResponse = await this.sendRequestAsync({
getMap: {}
}, playerId, playerToken, timeoutMs);
if (validation.isValidAppResponse(appResponse)) {
return appResponse;
}
else {
return appResponse;
}
}
/**
* Get the team info (callback version).
* Consumes tokens and then sends a request to retrieve team information.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {CallbackFunction} callback - The callback function that will be executed when a response is received.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
*
* @returns {Promise<ConsumeTokensError | Error | void>} Returns an error if token consumption fails or if there is
* an issue sending the request, otherwise returns void.
*/
async getTeamInfo(playerId, playerToken, callback, waitForReplenish = true) {
const tokenCost = RustPlus.REQUEST_GET_TEAM_INFO_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
return this.sendRequest({
getTeamInfo: {}
}, playerId, playerToken, callback);
}
/**
* Get the team info (async version).
* Consumes tokens and then sends a request to retrieve team information, returning a promise.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
* @param {number} [timeoutMs=10000] - Time (in milliseconds) to wait for a response before timing out.
*
* @returns {Promise<ConsumeTokensError | Error | rpi.AppResponse>} Returns a promise that resolves to the
* team info (AppResponse), or an error if
* token consumption fails or there is an
* issue with the request.
*/
async getTeamInfoAsync(playerId, playerToken, waitForReplenish = true, timeoutMs = RustPlus.REQUEST_GET_TEAM_INFO_TIMEOUT_MS) {
const tokenCost = RustPlus.REQUEST_GET_TEAM_INFO_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
const appResponse = await this.sendRequestAsync({
getTeamInfo: {}
}, playerId, playerToken, timeoutMs);
if (validation.isValidAppResponse(appResponse)) {
return appResponse;
}
else {
return appResponse;
}
}
/**
* Get the team chat (callback version).
* Consumes tokens and then sends a request to retrieve team chat.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {CallbackFunction} callback - The callback function that will be executed when a response is received.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
*
* @returns {Promise<ConsumeTokensError | Error | void>} Returns an error if token consumption fails or if there is
* an issue sending the request, otherwise returns void.
*/
async getTeamChat(playerId, playerToken, callback, waitForReplenish = true) {
const tokenCost = RustPlus.REQUEST_GET_TEAM_CHAT_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
return this.sendRequest({
getTeamChat: {}
}, playerId, playerToken, callback);
}
/**
* Get the team chat (async version).
* Consumes tokens and then sends a request to retrieve team chat, returning a promise.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
* @param {number} [timeoutMs=10000] - Time (in milliseconds) to wait for a response before timing out.
*
* @returns {Promise<ConsumeTokensError | Error | rpi.AppResponse>} Returns a promise that resolves to the
* team chat (AppResponse), or an error if
* token consumption fails or there is an
* issue with the request.
*/
async getTeamChatAsync(playerId, playerToken, waitForReplenish = true, timeoutMs = RustPlus.REQUEST_GET_TEAM_CHAT_TIMEOUT_MS) {
const tokenCost = RustPlus.REQUEST_GET_TEAM_CHAT_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
const appResponse = await this.sendRequestAsync({
getTeamChat: {}
}, playerId, playerToken, timeoutMs);
if (validation.isValidAppResponse(appResponse)) {
return appResponse;
}
else {
return appResponse;
}
}
/**
* Send a team message (callback version).
* Consumes tokens and then sends a request to send team message.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {string} message - The message to be sent in the team chat.
* @param {CallbackFunction} callback - The callback function that will be executed when a response is received.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
*
* @returns {Promise<ConsumeTokensError | Error | void>} Returns an error if token consumption fails or if there is
* an issue sending the request, otherwise returns void.
*/
async sendTeamMessage(playerId, playerToken, message, callback, waitForReplenish = true) {
const tokenCost = RustPlus.REQUEST_SEND_TEAM_MESSAGE_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
return this.sendRequest({
sendTeamMessage: {
message: message
}
}, playerId, playerToken, callback);
}
/**
* Send a team message (async version).
* Consumes tokens and then sends a request to send team message, returning a promise.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {string} message - The message to be sent in the team chat.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
* @param {number} [timeoutMs=10000] - Time (in milliseconds) to wait for a response before timing out.
*
* @returns {Promise<ConsumeTokensError | Error | rpi.AppResponse>} Returns a promise that resolves to the
* send team message (AppResponse), or an
* error if token consumption fails or there
* is an issue with the request.
*/
async sendTeamMessageAsync(playerId, playerToken, message, waitForReplenish = true, timeoutMs = RustPlus.REQUEST_SEND_TEAM_MESSAGE_TIMEOUT_MS) {
const tokenCost = RustPlus.REQUEST_SEND_TEAM_MESSAGE_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
const appResponse = await this.sendRequestAsync({
sendTeamMessage: {
message: message
}
}, playerId, playerToken, timeoutMs);
if (validation.isValidAppResponse(appResponse)) {
return appResponse;
}
else {
return appResponse;
}
}
/**
* Get entity info (callback version).
* Consumes tokens and then sends a request to retrieve entity information.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {number} entityId - The ID of the entity to retrieve information about.
* @param {CallbackFunction} callback - The callback function that will be executed when a response is received.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
* request.
*
* @returns {Promise<ConsumeTokensError | Error | void>} Returns an error if token consumption fails or if there is
* an issue sending the request, otherwise returns void.
*/
async getEntityInfo(playerId, playerToken, entityId, callback, waitForReplenish = true) {
const tokenCost = RustPlus.REQUEST_GET_ENTITY_INFO_TOKEN_COST;
const result = await this.consumeTokens(playerId, tokenCost, waitForReplenish);
if (result !== ConsumeTokensError.NoError)
return result;
return this.sendRequest({
entityId: entityId,
getEntityInfo: {}
}, playerId, playerToken, callback);
}
/**
* Get entity info (async version).
* Consumes tokens and then sends a request to retrieve entity information, returning a promise.
*
* @param {string} playerId - The steamId of the player making the request.
* @param {number} playerToken - The authentication token of the player making the request.
* @param {number} entityId - The ID of the entity to retrieve information about.
* @param {boolean} [waitForReplenish=true] - If true, wait until tokens are available before proceeding with the
*