From 06b8bfe133db0505aaa45f094712ae1bae97cb17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20P=C4=99dzich?= Date: Tue, 18 Feb 2025 12:02:38 +0100 Subject: [PATCH] feat: add 2022 spec car setups packet parser --- src/lib.rs | 5 ++- src/packets/car_setups.rs | 53 +++++++++++++++++++++++++++++++ src/packets/mod.rs | 65 ++++++++++++++++++++++++--------------- 3 files changed, 98 insertions(+), 25 deletions(-) create mode 100644 src/packets/car_setups.rs diff --git a/src/lib.rs b/src/lib.rs index 9b07cc0..6be16b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ pub mod constants; pub mod packets; use crate::constants::PacketId; -use crate::packets::{F1PacketEventData, F1PacketLapData, F1PacketMotionData, F1PacketParticipantsData, F1PacketSessionData}; +use crate::packets::{F1PacketCarSetupsData, F1PacketEventData, F1PacketLapData, F1PacketMotionData, F1PacketParticipantsData, F1PacketSessionData}; use binrw::io::Cursor; use binrw::{BinRead, BinReaderExt, BinResult}; @@ -84,4 +84,7 @@ pub struct F1PacketBody { /// List of participants in the race. #[br(if(packet_id == PacketId::Participants), args(packet_format))] pub participants: Option, + /// Car setups for each vehicle in the session. + #[br(if(packet_id == PacketId::CarSetups), args(packet_format))] + pub car_setups: Option, } diff --git a/src/packets/car_setups.rs b/src/packets/car_setups.rs new file mode 100644 index 0000000..0f2140c --- /dev/null +++ b/src/packets/car_setups.rs @@ -0,0 +1,53 @@ +use binrw::BinRead; +use serde::{Deserialize, Serialize}; + +#[derive( + BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, +)] +#[br(little, import(_packet_format: u16))] +pub struct CarSetupData { + /// Front wing aero + pub front_wing: u8, + /// Rear wing aero + pub rear_wing: u8, + /// Differential adjustment on throttle (percentage) + pub on_throttle: u8, + /// Differential adjustment off throttle (percentage) + pub off_throttle: u8, + /// Front camber angle (suspension geometry) + pub front_camber: f32, + /// Rear camber angle (suspension geometry) + pub rear_camber: f32, + /// Front toe angle (suspension geometry) + pub front_toe: f32, + /// Rear toe angle (suspension geometry) + pub rear_toe: f32, + /// Front suspension + pub front_suspension: u8, + /// Rear suspension + pub rear_suspension: u8, + /// Front anti-roll bar + pub front_anti_roll_bar: u8, + /// Rear anti-roll bar + pub rear_anti_roll_bar: u8, + /// Front ride height + pub front_suspension_height: u8, + /// Rear ride height + pub rear_suspension_height: u8, + /// Brake pressure (percentage) + pub brake_pressure: u8, + /// Brake bias + pub brake_bias: u8, + /// Rear left tyre pressure + pub rear_left_tyre_pressure: f32, + /// Rear right tyre pressure + pub rear_right_tyre_pressure: f32, + /// Front left tyre pressure + pub front_left_tyre_pressure: f32, + /// Front right tyre pressure + pub front_right_tyre_pressure: f32, + /// Ballast + pub ballast: u8, + /// Fuel load + pub fuel_load: f32, +} diff --git a/src/packets/mod.rs b/src/packets/mod.rs index ff899c7..df9b856 100644 --- a/src/packets/mod.rs +++ b/src/packets/mod.rs @@ -3,6 +3,7 @@ pub mod lap_data; pub mod motion; pub mod participants; pub mod session; +mod car_setups; use crate::constants::{ BrakingAssist, DynamicRacingLine, DynamicRacingLineType, ForecastAccuracy, @@ -16,6 +17,7 @@ use crate::packets::motion::CarMotionData; use crate::packets::participants::ParticipantsData; use crate::packets::session::{MarshalZone, WeatherForecastSample}; +use crate::packets::car_setups::CarSetupData; use binrw::BinRead; use serde::{Deserialize, Serialize}; use std::string::FromUtf8Error; @@ -201,6 +203,45 @@ pub struct F1PacketEventData { pub event_details: EventDataDetails, } +/// Data of participants in the session, mostly relevant for multiplayer. +#[non_exhaustive] +#[derive( + BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize, +)] +#[br( + little, + import(packet_format: u16), + assert( + num_active_cars <= MAX_NUM_CARS, + "Participants packet has an invalid number of active cars: {}", + num_active_cars + ) +)] +pub struct F1PacketParticipantsData { + /// Number of active cars in the data (no greater than 22) + #[br(map(u8_to_usize))] + pub num_active_cars: usize, + /// Data for all participants. + /// Should have a size equal to + /// [`num_active_cars`](field@F1PacketParticipantsData::num_active_cars) + #[br(count(num_active_cars), args{ inner: (packet_format,) })] + pub participants: Vec, +} + +/// Packet detailing car setups for cars in the race. +/// In multiplayer games, other player cars will appear as blank. +/// You will only be able to see your car setup and AI cars. +#[derive( + BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize, +)] +#[br(little, import(packet_format: u16))] +pub struct F1PacketCarSetupsData { + /// Setup data for all cars on track. + /// Should have a size of 22. + #[br(count(MAX_NUM_CARS), args{ inner: (packet_format,) })] + pub car_setups: Vec, +} + /// Extended motion data for player's car. Available as a: /// - part of [`F1PacketMotionData`] in the 2022 format /// - standalone packet from the 2023 format onwards @@ -252,30 +293,6 @@ pub struct F1PacketMotionExData { pub front_wheels_angle: f32, } -/// Data of participants in the session, mostly relevant for multiplayer. -#[derive( - BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize, -)] -#[br( - little, - import(packet_format: u16), - assert( - num_active_cars <= MAX_NUM_CARS, - "Participants packet has an invalid number of active cars: {}", - num_active_cars - ) -)] -pub struct F1PacketParticipantsData { - /// Number of active cars in the data (no greater than 22) - #[br(map(u8_to_usize))] - pub num_active_cars: usize, - /// Data for all participants. - /// Should have a size equal to - /// [`num_active_cars`](field@F1PacketParticipantsData::num_active_cars) - #[br(count(num_active_cars), args{ inner: (packet_format,) })] - pub participants: Vec, -} - pub(crate) fn u8_to_bool(value: u8) -> bool { value == 1 }