This is an unofficial NodeJS library for interacting with Smart Switches, Smart Alarms and various other things in the PC game Rust.
It communicates with the Rust Game Server via the WebSocket running on the port configured in your server.cfg
as app.port
.
The server owner needs to make sure their app.port
has been configured and opened in their firewall.
Also, feel free to check out my new rust project Atlas. It's an interactive map experience for Rust.
To use this library in your own NodeJS app, you can install it via npm
.
npm install @liamcottle/rustplus.js
Below is a list of convenience methods that are implemented for common requests in the RustPlus library. Examples of these can be found in the examples section.
turnSmartSwitchOn
Turn Smart Switch onturnSmartSwitchOff
Turn Smart Switch offsendTeamMessage
Send messages to Team ChatgetEntityInfo
Get current state of a Smart DevicesetEntityValue
Set the value of a Smart DevicegetInfo
Get info about the Rust ServergetMap
Fetch map info, which inclues a jpeg imagegetTime
Get the current in game timegetMapMarkers
Get map markers, such as vending machines and cargo/heligetTeamInfo
Get list of team members and positions on mapgetCameraFrame
Get a jpeg image from a CCTV Camera
More requests are available and can be found in the AppRequest
message section of the rustplus.proto protobuf file that I wrote by hand.
For requests that aren't available through a convenience method, you can still craft and send the requests manually with sendRequest
, as shown below. Have a look in the protobuf file to know what data you need to send.
// Send Team Message without using convenience method
rustplus.sendRequest({
sendTeamMessage: {
message: "Message for Team Chat",
},
}, (message) => {
console.log(message);
});
If you want a promise based API for sending requests, you can use sendRequestAsync
. You won't be able to use the convenience methods, but it's very straightforward to craft the request payloads manually. Check this example for using sendRequestAsync
.
More code examples can be found in the examples directory.
You will need to provide the following details to be able to connect:
- Server IP (or hostname)
- App Port (
app.port
inserver.cfg
) - Player Id (Your Steam ID)
- Player Token (Token from Server Pairing)
const RustPlus = require('@liamcottle/rustplus.js');
var rustplus = new RustPlus('ip', 'port', 'playerId', 'playerToken');
// wait until connected before sending commands
rustplus.on('connected', () => {
// ready to send requests
rustplus.sendTeamMessage('Hello from rustplus.js!');
});
// connect to rust server
rustplus.connect();
Note: You now need to call
connect
manually after creating aRustPlus
instance. The library no longer automatically connects.
You can turn a Smart Switch on or off by calling turnSmartSwitchOn
or turnSmartSwitchOff
with the entity id of the Smart Switch.
An optional callback function can be provided as the second parameter which will be called when a response has been received from the server for this specific request.
rustplus.turnSmartSwitchOn(1234567, (message) => {
console.log("turnSmartSwitchOn response message: " + JSON.stringify(message));
return true;
});
You need to be in a team before you can send messages to team chat.
rustplus.sendTeamMessage('message to team chat');
You can check the current status of a Smart Switch or Smart Alarm by calling getEntityInfo
with the entity id.
rustplus.getEntityInfo(1234567, (message) => {
console.log("getEntityInfo response message: " + JSON.stringify(message));
return true;
});
Once you have called getEntityInfo
at least once for an entity id, you will receive broadcast messages automatically from the Rust server when the entity's state changes between on and off.
If you don't call getEntityInfo
at least once, you will never receive the broadcast.
You can capture the broadcast like so:
rustplus.on('message', (message) => {
if(message.broadcast && message.broadcast.entityChanged){
var entityChanged = message.broadcast.entityChanged;
var entityId = entityChanged.entityId;
var value = entityChanged.payload.value;
console.log("entity " + entityId + " is now " + (value ? "active" : "inactive"));
}
});
The Storage Monitor that was recently added to Rust sends Entity Changed Broadcasts when items are added and removed from the Storage Container that the Storage Monitor is associated with.
You will receive two broadcasts for the Storage Monitor, one with the entityChanged.payload.value
set to true
and the second with the entityChanged.payload.value
set to false
. When using the official Rust+ app you'll see the storage monitor entity change to green, then back to grey.
Note that broadcasts are sent without player interaction only if tool cupboard changes to decaying state. Resources removed from a decay tick does not send a broadcast.
You can use the following snippet as an idea of how to listen for changes to a Storage Monitor and print out the current items in it.
As above, make sure to call getEntityInfo
with the Storage Monitor entity id so you are sent the broadcasts by the server.
rustplus.on('message', (message) => {
if(message.broadcast && message.broadcast.entityChanged){
var entityChanged = message.broadcast.entityChanged;
var entityId = entityChanged.entityId;
var value = entityChanged.payload.value;
var capacity = entityChanged.payload.capacity;
var items = entityChanged.payload.items;
// only print info when second broadcast is received
if(!value){
console.log(`entity ${entityId} has a capacity of ${capacity}`);
console.log(`entity ${entityId} contains ${items.length} item(s)`);
// print out the items in this storage entity
items.forEach((item) => {
console.log(item);
});
}
}
});
A message is a payload of data sent to you from the Rust Server. This shouldn't be confused with Chat Messages.
When you send a request to the Rust Server, you can optionally provide a callback which will be invoked when a response is received from the server for that specific request.
If you return true
from the callback, the response will be treated as handled.
When a message has been received and has not been handled by your callback, it will be emitted via the message
event.
You can register a listener to catch all received messages like so:
rustplus.on('message', (message) => {
console.log("message received: " + JSON.stringify(message));
});
Here's a list of the emitted events:
connecting
: When we are connecting to the Rust Server.connected
: When we are connected to the Rust Server.disconnected
: When we are disconnected from the Rust Server.error
: When something goes wrong.message
: When anAppMessage
has been received from the Rust Server.request
: When anAppRequest
has been sent to the Rust Server.
The Rust+ websocket protocol allows you to fetch CCTV Camera frames through the getCameraFrame
request. However, these aren't available in the official Rust+ app yet and are also disabled server side.
It is possible to enable CCTV Camera frames if you are the server admin by running the following command in the F1 console.
cctvrender.enabled true
Note: This will not enable CCTV Cameras in the Rust+ app, but it will allow you to request jpeg packets through the websocket with the
getCameraFrame
request.
CCTV Example:
rustplus.getCameraFrame("DOME1", 0, (message) => {
console.log(message);
return true;
});
In order to use this library, we need to get the Server Information to connect to the App WebSocket as well as get the Entity Ids of the Smart Alarms and Smart switches we want to interact with.
The way this works in the official Rust+ app is documented in the Pairing Flow document in the docs folder.
You can gather the required information in a couple of ways.
If you just want to interact with your own private server for testing, you won't need to utilize the Rust Companion API server as you can already access all of the information you need from the server itself.
- You already have access to your
Server IP
andApp Port
configured in yourserver.cfg
file. - You can find your
playerToken
in the sqlite3 database fileplayer.tokens.db
with the following command on a Linux server.sqlite3 player.tokens.db "select * from data;" ".exit"
- You will get output like so:
xxxxxxxxxxxxxxxxx|yyyyyyyyy
xxxxxxxxxxxxxxxxx
is theplayerId
yyyyyyyyy
is theplayerToken
. (It can be a positive or negative integer.)
- As an admin you can use the command
lookingat_debug
to show/hide the entity id of what you are currently looking at. I like to bind it to a key withbind o lookingat_debug
.
I have put together a command line tool which will do everything required to receive Pairing Notifications from the Rust Companion API when you click the "Pair" buttons in game.
Before you can listen for Pairing Notifications, you need to register with FCM, Expo and link your Steam Account with Rust+. Conveniently, you can do this by running the following command.
npx @liamcottle/rustplus.js fcm-register
A custom Google Chrome browser will be launched. This will take you to the Rust Companion website to log in with your Steam account.
Note: You must have Google Chrome installed to use
fcm-register
After successfully registering, you can listen for Pairing Notifications
npx @liamcottle/rustplus.js fcm-listen
Example Output
{
img: '',
port: '28017',
ip: 'your-server-ip',
name: "your-server-name",
id: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
type: 'server',
url: '',
desc: 'your-server-description',
playerId: 'your-steam-id',
playerToken: 'your-player-token'
}
The command line tool allows you to set a custom config file for saving and loading your credentials. This is helpful if you want to register on your local pc, and copy the config to another server.
npx @liamcottle/rustplus.js --config-file=/path/to/config.json <command>
If you want to run the latest changes to the CLI tool, you can run it like so:
git clone https://github.com/liamcottle/rustplus.js
cd rustplus.js
npm install
node cli/index.js <command>
The Rust game server enforces a limit on how many connections can be made to the Rust+ websocket, and how many connections can be made by the same IP Address at once.
- Max Connections:
500
is default- Can be adjusted with server var
app.maxconnections
- Can be adjusted with server var
- Max Connections per IP:
5
is default- Can be adjusted with server var
app.maxconnectionsperip
- Can be adjusted with server var
The Rust game server enforces rate limits on requests sent to the Rust+ websocket. This is done with a token bucket approach.
The token bucket gives you a maximum amount of tokens, and replenishes them over time at a fixed rate.
Here is a list of the rate limits enforced by the Rust game server:
- Requests per IP Address
50 tokens limit, 15 tokens replenished per second.
- Requests per Player ID
25 tokens limit, 3 tokens replenished per second.
- Requests for Server Pairing
5 tokens limit, 0.1 tokens replenished per second.
Rate limits can be found in the CompanionServer.Listener
class in Assembly-CSharp.dll
from the game server files.
Below is the token cost per request type:
Default: 1
--
CameraFrame: 2
CheckSubscription: 1
EntityInfo: 1
Info: 1
Map: 5
MapMarkers: 1
PromoteToLeader: 1
SendTeamChat: 2
SetEntityValue: 1
SetSubscription: 1
TeamInfo: 1
Time: 1
If you want this project taken down, feel free to message me! However this project only allows you to automate the same actions you can already do in the official Rust+ app.
I'm looking forward to seeing all of the projects the Rust community come up with! Here are some ideas I came up with:
- Discord Bot
- Sync Team Chat in-game and on Discord.
- Send messages to Discord when Smart Alarms are triggered.
- Send messages to Discord when Cargo, Heli or Crate events spawn on the map.
- Controlling Smart Devices via Discord messages.
- Vending Machine Search Tool
- Find a specific item for sale on the map
- Statistics on what items are commonly sold, and for what prices.