Skip to content

kunihir0/rustplus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rustplus

A Rust client for the Rust+ companion app protocol. This library provides a native, asynchronous interface for interacting with Rust game servers.

Features

  • Asynchronous API: Built on tokio and tokio-tungstenite.
  • Full Protocol Coverage: Support for server info, map markers, team chat, and entity control.
  • Camera Support: Native decoding of camera rays into PNG frames using the image crate.
  • Automatic Rate Limiting: Transparently manages token buckets for IP and Player ID limits.
  • Strongly Typed: Automatically generated Protobuf bindings via prost.

Acquiring a Player Token

To connect to a server, you must provide a valid player_token generated by the Rust server. The only automated way to retrieve this token dynamically (e.g., when a user clicks "Pair" in-game) is to register an Android FCM/GCM device and listen for the pairing push notification.

If you are building a Discord bot or application that requires users to pair servers dynamically, you will need to use our companion crate: push-receiver

push-receiver acts as a mock Android device to catch the pairing notifications and extract the tokens, which you can then pass into rustplus.

Dynamic Pairing Example

use push_receiver::PushReceiver;
use rustplus::RustPlusClient;
use serde_json::Value;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. Connect to FCM using the Rust+ Sender ID
    let (_receiver, mut rx) = PushReceiver::builder("1056586548777")
        .connect()
        .await?;

    println!("Waiting for pairing notification (Click 'Pair' in Rust)...");

    // 2. Listen for incoming push messages
    while let Some(msg) = rx.recv().await {
        for item in msg.app_data {
            let val = item.value.trim();
            if !val.starts_with('{') { continue; }

            // 3. Parse the pairing payload
            if let Ok(body) = serde_json::from_str::<Value>(val) {
                if let (Some(ip), Some(port), Some(token), Some(steam_id)) = (
                    body["ip"].as_str(),
                    body["port"].as_u64(),
                    body["playerToken"].as_i64(),
                    body["playerId"].as_u64(),
                ) {
                    println!("Received pairing info for {}:{}", ip, port);

                    // 4. Use the extracted token to connect the RustPlusClient
                    let mut rp_client = RustPlusClient::new(
                        ip, port as u16, steam_id, token as i32, false
                    );
                    
                    rp_client.connect().await?;
                    
                    let info = rp_client.get_info().await?;
                    if let Some(resp) = info.response {
                        println!("Connected successfully to: {:?}", resp.get_info);
                    }
                    return Ok(());
                }
            }
        }
    }
    Ok(())
}

Usage

use rustplus::RustPlusClient;

#[tokio::main]
async fn main() -> rustplus::Result<()> {
    let mut client = RustPlusClient::new(
        "127.0.0.1", // Server IP
        28082,       // App Port
        7656119...,  // Steam ID
        -12345678,   // Player Token
        false,       // Use Facepunch Proxy
    );

    client.connect().await?;

    let info = client.get_info().await?;
    if let Some(resp) = info.response {
        if let Some(get_info) = resp.get_info {
            println!("Server Name: {}", get_info.name);
        }
    }

    client.send_team_message("Hello from Rust!").await?;

    Ok(())
}

Camera Usage

let mut camera = client.get_camera("DOME1");
camera.subscribe().await?;

let mut frames = camera.subscribe_frames();
while let Ok(png_bytes) = frames.recv().await {
    // png_bytes contains the rendered frame
}

Configuration

The client respects the following default server limits:

  • IP Limit: 50 tokens, 15/sec replenishment.
  • Player Limit: 25 tokens, 3/sec replenishment.

About

This library lets you connect to and control Rust game servers using the Rust+ app.

Topics

Resources

Stars

Watchers

Forks

Contributors

Languages