liamcottle / rustplus.js

Unofficial NodeJS library for controlling Smart Switches in the PC game Rust
232 stars 47 forks source link

Camera Frames #2

Closed PhilippHeuer closed 4 years ago

PhilippHeuer commented 4 years ago

I saw you added some information about cctv frames and i wanted to check that out.

I have some trouble with getting it to work on my testserver, i enabled cctv rendering but the requests always return 0 bytes in GetCameraFrame.getJpgImage. The idenfiier it obv. the cctv name, but i'm not sure what i need to enter into the frame parameter, i tried 0, 90 (fov) and a few others but no success.

Maybe we could add some comments to request/response parameters in the protoc file for the generated code, as described here https://developers.google.com/protocol-buffers/docs/proto#adding_comments

And thanks again for finding all of this out, this is a awesome library.

liamcottle commented 4 years ago

I haven't had a chance to document all my research on CCTV yet, but the way that it works is rather interesting. I'll document a bit of it here.

Since the game server doesn't actually render the world (the players client does), the way this currently works is when you request a CCTV camera frame via the Rust+ websocket, the game server will look for any players that are near the CCTV camera (within the configured cctvrender.maxdistance). Those nearby players are then scored based on various things, and one of the nearby players is chosen to render the view of the CCTV camera.

The server sends a packet to the players client asking it to render the frame. The rendered frame is sent back to the game server from the players client, and the server then passes it to the Rust+ websocket that requested it (as well as caching it so players that request the same frame get it without a re-render).

If no players are nearby to render a CCTV camera, you will not get a jpeg frame, you will instead receive an error with the message unavailable. (See the snippet below)

Here's the server variables you can play around with. I adjusted cctvrender.maxdistance to 999999 which gets it to render if you are far away on the map, but if the player is so far away, the objects in game aren't actually loaded in, so you only see terrain or water etc.

Give it a go by teleporting to Small Oil Rig and using the CCTV identifier OILRIG1L1.

Here's a snippet on how to pull frames. Note that you can just send 0 as the frame number, and the server will just return the latest frame and its frame number to you. The frame number is used internally by the server so it can return a cached frame without having the request a new render.

// request a cctv camera frame
rustplus.sendRequest({
    getCameraFrame: {
        identifier: "OILRIG1L1",
        frame: 0,
    }
}, (message) => {

    // check if we received a frame
    if(message.response.cameraFrame){

        // get the server frame number and the jpeg data
        var frame = message.response.cameraFrame.frame;
        var jpgImage = message.response.cameraFrame.jpgImage;

        // save the jpeg to a file
        fs.writeFileSync(`frames/${frame}.jpg`, jpgImage);

        // handled it
        return true;

    }

    // check for error
    if(message.response.error){

        // get the error message
        var errorMessage = message.response.error.error;

        if(errorMessage === "not_found"){
            // camera identifier doesn't exist
            console.log("CCTV Camera Not Found");
        } else if(errorMessage === "unavailable"){
            // no players nearby to render camera
            console.log("No players nearby to render CCTV Camera");
        } else {
            // some other error
            console.log(`Error: ${errorMessage}`);
        }

    }

});

Also thanks for the feedback! I'll be adding comments etc as I research more, so keep watch for those.

PhilippHeuer commented 4 years ago

Thanks a lot for all this detailed information, i got it to work :)