Expand description
§subtr-actor
subtr-actor is a versatile library designed to facilitate the
processes of working with and extracting data from Rocket League replays.
Utilizing the powerful boxcars library for parsing, subtr-actor
simplifies (or ‘subtracts’, as hinted by its name) the underlying
actor-based structure of replay files, making them more accessible and
easier to manipulate.
§Overview of Key Components
-
ReplayProcessor: This struct is at the heart of subtr-actor’s replay processing capabilities. In its main entry point,ReplayProcessor::process, it pushes network frames from theboxcars::Replaythat it is initialized with though anActorStateModelerinstance, calling theCollectorinstance that is provided as an argument as it does so. TheCollectoris provided with a reference to theReplayProcessoreach time the it is invoked, which allows it to use the suite of helper methods which greatly assist in the navigation of the actor graph and the retrieval of information about the current game state. -
Collector: This trait outlines the blueprint for data collection from replays. TheCollectorinterfaces with aReplayProcessor, handling frame data and guiding the pace of replay progression withTimeAdvance. It is typically invoked repeatedly through theReplayProcessor::processmethod as the replay is processed frame by frame. -
FrameRateDecorator: This struct decorates aCollectorimplementation with a target frame duration, controlling the frame rate of the replay processing.
§Collector implementations
subtr-actor also includes implementations of the Collector trait:
-
NDArrayCollector: ThisCollectorimplementations translates frame-based replay data into a 2 dimensional array in the form of a::ndarray::Array2instance. The exact data that is recorded in each frame can be configured with theFeatureAdderandPlayerFeatureAdderinstances that are provided to its constructor (NDArrayCollector::new). Extending the exact behavior ofNDArrayCollectoris thus possible with user definedFeatureAdderandPlayerFeatureAdder, which is made easy with thebuild_global_feature_adder!andbuild_player_feature_adder!macros. The::ndarray::Array2produced byNDArrayCollectoris ideal for use with machine learning libraries like pytorch and tensorflow. -
ReplayDataCollector: ThisCollectorimplementation provides an easy way to get a serializable to e.g. json (thoughserde::Serialize) representation of the replay. The representation differs from what you might get from e.g. rawboxcarsin that it is not a complicated graph of actor objects, but instead something more natural where the data associated with each entity in the game is grouped together.
§Examples
§Getting JSON
fn get_json(filepath: std::path::PathBuf) -> anyhow::Result<String> {
let data = std::fs::read(filepath.as_path())?;
let replay = boxcars::ParserBuilder::new(&data)
.must_parse_network_data()
.on_error_check_crc()
.parse()?;
Ok(subtr_actor::ReplayDataCollector::new()
.get_replay_data(&replay)
.map_err(|e| e.variant)?
.as_json()?)
}§Getting a ::ndarray::Array2
In the following example, we demonstrate how to use boxcars,
NDArrayCollector and FrameRateDecorator to write a function that
takes a replay filepath and collections of features adders and returns a
ReplayMetaWithHeaders along with a ::ndarray::Array2 . The resulting
::ndarray::Array2 would be appropriate for use in a machine learning
context. Note that ReplayProcessor is also used implicitly here in the
Collector::process_replay
use subtr_actor::*;
fn get_ndarray_with_info_from_replay_filepath(
filepath: std::path::PathBuf,
feature_adders: FeatureAdders<f32>,
player_feature_adders: PlayerFeatureAdders<f32>,
fps: Option<f32>,
) -> anyhow::Result<(ReplayMetaWithHeaders, ::ndarray::Array2<f32>)> {
let data = std::fs::read(filepath.as_path())?;
let replay = boxcars::ParserBuilder::new(&data)
.must_parse_network_data()
.on_error_check_crc()
.parse()?;
let mut collector = NDArrayCollector::new(feature_adders, player_feature_adders);
FrameRateDecorator::new_from_fps(fps.unwrap_or(10.0), &mut collector)
.process_replay(&replay)
.map_err(|e| e.variant)?;
Ok(collector.get_meta_and_ndarray().map_err(|e| e.variant)?)
}
fn get_ndarray_with_default_feature_adders(
filepath: std::path::PathBuf,
) -> anyhow::Result<(ReplayMetaWithHeaders, ::ndarray::Array2<f32>)> {
get_ndarray_with_info_from_replay_filepath(
filepath,
vec![
InterpolatedBallRigidBodyNoVelocities::arc_new(0.003),
CurrentTime::arc_new(),
],
vec![
InterpolatedPlayerRigidBodyNoVelocities::arc_new(0.003),
PlayerBoost::arc_new(),
PlayerAnyJump::arc_new(),
PlayerDemolishedBy::arc_new(),
],
Some(30.0),
)
}§Using NDArrayCollector::from_strings
In the second function in the example above, we see the use of feature
adders like InterpolatedPlayerRigidBodyNoVelocities. The feature adders
that are included with subtr_actor can all be found in the
crate::collector::ndarray module. It is also possible to access these
feature adders by name with strings, which can be useful when implementing
bindings for other languages since those languages may not be able to access
rust structs an instantiate them easily or at all.
pub static DEFAULT_GLOBAL_FEATURE_ADDERS: [&str; 1] = ["BallRigidBody"];
pub static DEFAULT_PLAYER_FEATURE_ADDERS: [&str; 3] =
["PlayerRigidBody", "PlayerBoost", "PlayerAnyJump"];
fn build_ndarray_collector(
global_feature_adders: Option<Vec<String>>,
player_feature_adders: Option<Vec<String>>,
) -> subtr_actor::SubtrActorResult<subtr_actor::NDArrayCollector<f32>> {
let global_feature_adders = global_feature_adders.unwrap_or_else(|| {
DEFAULT_GLOBAL_FEATURE_ADDERS
.iter()
.map(|i| i.to_string())
.collect()
});
let player_feature_adders = player_feature_adders.unwrap_or_else(|| {
DEFAULT_PLAYER_FEATURE_ADDERS
.iter()
.map(|i| i.to_string())
.collect()
});
let global_feature_adders: Vec<&str> = global_feature_adders.iter().map(|s| &s[..]).collect();
let player_feature_adders: Vec<&str> = player_feature_adders.iter().map(|s| &s[..]).collect();
subtr_actor::NDArrayCollector::<f32>::from_strings(
&global_feature_adders,
&player_feature_adders,
)
}Re-exports§
pub use crate::actor_state::*;pub use crate::collector::*;pub use crate::constants::*;pub use crate::error::*;pub use crate::processor::*;pub use crate::util::*;
Modules§
Macros§
- build_
global_ feature_ adder - This macro creates a global
FeatureAdderstruct and implements the necessary traits to add the calculated features to the data matrix. The macro exports a struct with the same name as passed in the parameter. The number of column names and the length of the feature array returned by$prop_getterare checked at compile time to ensure they match, in line with theLengthCheckedFeatureAddertrait. The output struct also provides an implementation of theFeatureAddertrait via theimpl_feature_adder!macro, allowing it to be used in contexts where aFeatureAdderobject is required. - build_
player_ feature_ adder - This macro creates a player feature adder struct and implements the
necessary traits to add the calculated player-specific features to the data
matrix. The macro exports a struct with the same name as passed in the
parameter. The number of column names and the length of the feature array
returned by
$prop_getterare checked at compile time to ensure they match, in line with theLengthCheckedPlayerFeatureAddertrait. The output struct also provides an implementation of thePlayerFeatureAddertrait via theimpl_player_feature_adder!macro, allowing it to be used in contexts where aPlayerFeatureAdderobject is required. - convert_
all - A macro that tries to convert each provided item into a type. If any of the conversions fail, it short-circuits and returns the error.
- convert_
all_ floats - A convenience macro that uses the
convert_allmacro with theconvert_float_conversion_errorfunction for error handling. - global_
feature_ adder - This macro is used to implement necessary traits for an existing struct to
add the calculated features to the data matrix. This macro is particularly
useful when the feature adder needs to be instantiated with specific
parameters. The number of column names and the length of the feature array
returned by
$prop_getterare checked at compile time to ensure they match. - impl_
feature_ adder - A macro to provide an automatic implementation of the
FeatureAddertrait for types that implementLengthCheckedFeatureAdder. This allows you to take advantage of the compile-time guarantees provided byLengthCheckedFeatureAdder, while still being able to use your type in contexts that require aFeatureAdderobject. This macro is used to bridge the gap between the two traits, as Rust’s type system does not currently provide a way to prove to the compiler that there will always be exactly one implementation ofLengthCheckedFeatureAdderfor each type. - impl_
player_ feature_ adder - A macro to provide an automatic implementation of the
PlayerFeatureAddertrait for types that implementLengthCheckedPlayerFeatureAdder. This allows you to take advantage of the compile-time guarantees provided byLengthCheckedPlayerFeatureAdder, while still being able to use your type in contexts that require aPlayerFeatureAdderobject. This macro is used to bridge the gap between the two traits, as Rust’s type system does not currently provide a way to prove to the compiler that there will always be exactly one implementation ofLengthCheckedPlayerFeatureAdderfor each type. - player_
feature_ adder - This macro is used to implement necessary traits for an existing struct to
add the calculated player-specific features to the data matrix. This macro
is particularly useful when the feature adder needs to be instantiated with
specific parameters. The number of column names and the length of the
feature array returned by
$prop_getterare checked at compile time to ensure they match.