Expand description
SDK for writing plugins for BakkesMod, a mod framework for Rocket League.
This SDK is an alternative to the C++ SDK found here, allowing to write plugins in Rust. Plugins built with the Rust SDK can be loaded into the game in the exact same way as C++ plugins.
Note however that not all functionality in the C++ SDK is available here yet, and importantly, the Rust SDK has had very little testing, so some things might be completely broken.
§Prerequisites
Make sure you have installed Rust and BakkesMod.
Also, add an environment variable called BAKKESMOD_LIB_PATH
containing the path to pluginsdk.lib
(e.g. C:\Program Files (x86)\Steam\steamapps\common\rocketleague\Binaries\Win64\bakkesmod\bakkesmodsdk\lib
).
§Create the project
Create a new Rust library project with cargo new --lib <pluginname>
.
Add the following to the generated Cargo.toml
:
[dependencies]
bakkesmod = "0.2"
[lib]
name = "mycoolplugin"
crate_type = ["cdylib"]
Write your plugin code in src/lib.rs
(and possibly add more files).
Make sure you have exactly one function with the #[plugin_init]
attribute. This function will be called when the plugin is loaded.
§Building
Use cargo build
or cargo build --release
to build. A <pluginname>.dll
file is created in target/debug
or target/release
.
Copy this file to your bakkesmod/plugins
folder. It can now be loaded in-game with plugin load <pluginname>
.
§Guide
See also the examples directory on GitHub for some examples.
BakkesMod plugins are loaded in-game using the plugin load <pluginname>
command in the console, or automatically when listed in
the plugins.cfg
file. When a plugin is loaded, the function with the plugin_init
attribute is executed. It makes sense to
call this function something like on_load
.
After this, plugin code is only executed through callbacks, which can trigger when e.g. a game event happens, or a console command
is executed. Typically, the on_load
function will register these callbacks, and the rest of the plugin’s execution happens
inside these callbacks.
As an example:
use bakkesmod::{game, console};
#[plugin_init]
pub fn on_load() {
// register a 'notifier' (a console command)
console::register_notifier("my_notifier", Box::new(move |params: Vec<String>| {
// callback code
}));
// register a hook on a game event
game::hook_event("Function Engine.GameViewportClient.Tick", Box::new(move || {
// callback code
}));
// use a normal function instead of a lambda
game::hook_event("Function TAGame.Car_TA.ApplyBallImpactForces", Box::new(my_callback));
}
fn my_callback() {
// callback code
}
BakkesMod-specific functionality like hooking, registering notifiers or drawables, is found in the
game
and console
modules.
The wrappers::unreal
module contains auto-generated wrappers around game classes, that are written in unrealscript.
Since Rust doesn’t have struct inheritance, and since BakkesMod provides only methods on these classes anyway,
traits are used to model functionality on these wrappers.
This means that each game object is represented as simple XXXWrapper
struct, without any methods.
Methods on these wrappers are implemented as part of traits, with names XXX
(without Wrapper).
For example, the CarWrapper
struct implementents the Car
trait, which allows you to call e.g. demolish
(defined in Car
) on a CarWrapper
instance. CarWrapper
also implements the Vehicle
, RBActor
and Actor
traits,
so all methods defined in those traits are also callable on a CarWrapper
instance. This is how the unrealscript
inheritance is mimicked.
It’s also recommended to import the prelude
module (use bakkesmod::prelude::*;
)
so that all macros are brought into scope.
Macros include log_console!
(print to the in-game console using the same formatting as Rust’s println!
),
and vec3!
and vec2!
for creating vectors.