diff --git a/src/constants/mod.rs b/src/constants/mod.rs index adff2cb..1b90260 100644 --- a/src/constants/mod.rs +++ b/src/constants/mod.rs @@ -1001,3 +1001,27 @@ pub enum RedFlags { Standard = 2, Increased = 3, } + +#[non_exhaustive] +#[derive( + BinRead, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, +)] +#[br(little, repr(u8))] +pub enum SafetyCarType { + None = 0, + Full = 1, + Virtual = 2, + FormationLap = 3, +} + +#[non_exhaustive] +#[derive( + BinRead, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, +)] +#[br(little, repr(u8))] +pub enum SafetyCarEventType { + Deployed = 0, + Returning = 1, + Returned = 2, + ResumeRace = 3, +} diff --git a/src/lib.rs b/src/lib.rs index a4d4516..ab822be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ use crate::packets::{ u8_to_usize, F1PacketCarDamage, F1PacketCarSetups, F1PacketCarStatus, F1PacketCarTelemetry, F1PacketEvent, F1PacketFinalClassification, F1PacketLap, F1PacketLobbyInfo, F1PacketMotion, F1PacketMotionEx, F1PacketParticipants, - F1PacketSession, F1PacketSessionHistory, F1PacketTyreSets, + F1PacketSession, F1PacketSessionHistory, F1PacketTimeTrial, F1PacketTyreSets, }; use binrw::io::Cursor; @@ -125,4 +125,8 @@ pub struct F1PacketBody { /// Available from the 2023 format onwards. #[br(if(packet_id == PacketId::MotionEx), args(packet_format))] pub motion_ex: Option, + /// Extra information that's only relevant to time trial game mode. + /// Available from the 2024 format onwards. + #[br(if(packet_id == PacketId::TimeTrial), args(packet_format))] + pub time_trial: Option, } diff --git a/src/packets/car_damage.rs b/src/packets/car_damage.rs index 17e7e92..2530d16 100644 --- a/src/packets/car_damage.rs +++ b/src/packets/car_damage.rs @@ -18,44 +18,44 @@ pub struct CarDamageData { /// See [`wheel_index`](mod@crate::constants::wheel_index) /// for wheel order. pub brakes_damage: [u8; 4], - /// Front left wing damage (percentage) + /// Front left wing damage (percentage). pub front_left_wing_damage: u8, - /// Front right wing damage (percentage) + /// Front right wing damage (percentage). pub front_right_wing_damage: u8, - /// Rear wing damage (percentage) + /// Rear wing damage (percentage). pub rear_wing_damage: u8, - /// Floor damage (percentage) + /// Floor damage (percentage). pub floor_damage: u8, - /// Diffuser damage (percentage) + /// Diffuser damage (percentage). pub diffuser_damage: u8, - /// Sidepod damage (percentage) + /// Sidepod damage (percentage). pub sidepod_damage: u8, - /// Whether DRS has failed + /// Whether DRS has failed. #[br(try_map(u8_to_bool))] pub drs_fault: bool, - /// Whether ERS has failed + /// Whether ERS has failed. #[br(try_map(u8_to_bool))] pub ers_fault: bool, - /// Gearbox damage (percentage) + /// Gearbox damage (percentage). pub gearbox_damage: u8, - /// Engine damage (percentage) + /// Engine damage (percentage). pub engine_damage: u8, - /// Engine MGU-H wear (percentage) + /// Engine MGU-H wear (percentage). pub engine_mguh_wear: u8, - /// Engine ES wear (percentage) + /// Engine ES wear (percentage). pub engine_es_wear: u8, - /// Engine CE wear (percentage) + /// Engine CE wear (percentage). pub engine_ce_wear: u8, - /// Engine ICE wear (percentage) + /// Engine ICE wear (percentage). pub engine_ice_wear: u8, - /// Engine MGU-K wear (percentage) + /// Engine MGU-K wear (percentage). pub engine_mguk_wear: u8, - /// Engine TC wear (percentage) + /// Engine TC wear (percentage). pub engine_tc_wear: u8, - /// Whether the engine has blown + /// Whether the engine has blown. #[br(try_map(u8_to_bool))] pub engine_blown: bool, - /// Whether the engine has seized + /// Whether the engine has seized. #[br(try_map(u8_to_bool))] pub engine_seized: bool, } diff --git a/src/packets/car_setups.rs b/src/packets/car_setups.rs index bd01218..92e3b5a 100644 --- a/src/packets/car_setups.rs +++ b/src/packets/car_setups.rs @@ -5,48 +5,48 @@ 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 + /// Front wing aero. pub front_wing: u8, - /// Rear wing aero + /// Rear wing aero. pub rear_wing: u8, - /// Differential adjustment on throttle (percentage) + /// Differential adjustment on throttle (percentage). pub on_throttle: u8, - /// Differential adjustment off throttle (percentage) + /// Differential adjustment off throttle (percentage). pub off_throttle: u8, - /// Front camber angle (suspension geometry) + /// Front camber angle (suspension geometry). pub front_camber: f32, - /// Rear camber angle (suspension geometry) + /// Rear camber angle (suspension geometry). pub rear_camber: f32, - /// Front toe angle (suspension geometry) + /// Front toe angle (suspension geometry). pub front_toe: f32, - /// Rear toe angle (suspension geometry) + /// Rear toe angle (suspension geometry). pub rear_toe: f32, - /// Front suspension + /// Front suspension. pub front_suspension: u8, - /// Rear suspension + /// Rear suspension. pub rear_suspension: u8, - /// Front anti-roll bar + /// Front anti-roll bar. pub front_anti_roll_bar: u8, - /// Rear anti-roll bar + /// Rear anti-roll bar. pub rear_anti_roll_bar: u8, - /// Front ride height + /// Front ride height. pub front_suspension_height: u8, - /// Rear ride height + /// Rear ride height. pub rear_suspension_height: u8, - /// Brake pressure (percentage) + /// Brake pressure (percentage). pub brake_pressure: u8, - /// Brake bias + /// Brake bias. pub brake_bias: u8, - /// Rear left tyre pressure + /// Rear left tyre pressure. pub rear_left_tyre_pressure: f32, - /// Rear right tyre pressure + /// Rear right tyre pressure. pub rear_right_tyre_pressure: f32, - /// Front left tyre pressure + /// Front left tyre pressure. pub front_left_tyre_pressure: f32, - /// Front right tyre pressure + /// Front right tyre pressure. pub front_right_tyre_pressure: f32, - /// Ballast + /// Ballast. pub ballast: u8, - /// Fuel load + /// Fuel load. pub fuel_load: f32, } diff --git a/src/packets/car_status.rs b/src/packets/car_status.rs index 7364842..ad55d70 100644 --- a/src/packets/car_status.rs +++ b/src/packets/car_status.rs @@ -9,15 +9,7 @@ use serde::{Deserialize, Serialize}; #[non_exhaustive] #[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)] -#[br( - little, - import(packet_format: u16), - assert( - max_gears <= 9, - "Car status entry has an invalid max number of gears: {}", - max_gears - ) -)] +#[br(little, import(packet_format: u16))] pub struct CarStatusData { /// How much traction control is enabled. pub traction_control: TractionControl, @@ -42,6 +34,13 @@ pub struct CarStatusData { /// Car's idle RPM. pub idle_rpm: u16, /// Maximum number of gears. + #[br( + assert( + max_gears <= 9, + "Car status entry has an invalid max number of gears: {}", + max_gears + ) + )] pub max_gears: u8, /// Whether DRS can be used (might be unknown). pub drs_allowed: DrsAllowed, diff --git a/src/packets/car_telemetry.rs b/src/packets/car_telemetry.rs index f88317b..7067b9b 100644 --- a/src/packets/car_telemetry.rs +++ b/src/packets/car_telemetry.rs @@ -6,52 +6,54 @@ use serde::{Deserialize, Serialize}; #[non_exhaustive] #[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)] -#[br( - little, - import(_packet_format: u16), - assert( - (0.0..=1.0).contains(&throttle), - "Car telemetry entry has an invalid throttle value: {}", - throttle - ), - assert( - (-1.0..=1.0).contains(&steer), - "Car telemetry entry has an invalid steering lock value: {}", - steer - ), - assert( - (0.0..=1.0).contains(&brake), - "Car telemetry entry has an invalid brake value: {}", - brake - ), - assert( - clutch <= 100, - "Car telemetry entry has an invalid clutch value: {}", - clutch - ), - assert( - (-1..=8).contains(&gear), - "Car telemetry entry has an invalid gear value: {}", - gear - ), - assert( - rev_lights_percent <= 100, - "Car telemetry entry has an invalid rev lights percentage: {}", - rev_lights_percent - ), -)] +#[br(little, import(_packet_format: u16))] pub struct CarTelemetryData { /// Speed of the car in kilometres per hour. pub speed: u16, /// Amount of throttle applied. Value in range `(0.0..=1.0)`. + #[br( + assert( + (0.0..=1.0).contains(&throttle), + "Car telemetry entry has an invalid throttle value: {}", + throttle + ), + )] pub throttle: f32, /// Steering lock. Value in range `(-1.0..=1.0)`. + #[br( + assert( + (-1.0..=1.0).contains(&steer), + "Car telemetry entry has an invalid steering lock value: {}", + steer + ), + )] pub steer: f32, /// Amount of brake applied. Value in range `(0.0..=1.0)`. + #[br( + assert( + (0.0..=1.0).contains(&brake), + "Car telemetry entry has an invalid brake value: {}", + brake + ), + )] pub brake: f32, /// Amount of clutch applied (percentage). + #[br( + assert( + clutch <= 100, + "Car telemetry entry has an invalid clutch value: {}", + clutch + ), + )] pub clutch: u8, /// Selected gear. Neutral = 0, reverse = -1. + #[br( + assert( + (-1..=8).contains(&gear), + "Car telemetry entry has an invalid gear value: {}", + gear + ), + )] pub gear: i8, /// Engine RPM. pub engine_rpm: u16, @@ -59,6 +61,13 @@ pub struct CarTelemetryData { #[br(try_map(u8_to_bool))] pub drs_enabled: bool, /// Rev lights indicator (percentage). + #[br( + assert( + rev_lights_percent <= 100, + "Car telemetry entry has an invalid rev lights percentage: {}", + rev_lights_percent + ), + )] pub rev_lights_percent: u8, /// Bitmap of active rev lights. #[br(map(RevLights::from_bits_truncate))] diff --git a/src/packets/event.rs b/src/packets/event.rs index a6b1bc2..f696cef 100644 --- a/src/packets/event.rs +++ b/src/packets/event.rs @@ -1,12 +1,14 @@ use super::{u8_to_bool, u8_to_usize}; -use crate::constants::{ButtonStatus, InfringementType, PenaltyType}; +use crate::constants::{ + ButtonStatus, InfringementType, PenaltyType, SafetyCarEventType, SafetyCarType, +}; use binrw::BinRead; use serde::{Deserialize, Serialize}; #[non_exhaustive] -#[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] -#[br(little)] +#[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)] +#[br(little, import(_packet_format: u16))] pub enum EventDataDetails { /// Sent when the session starts. #[br(magic = b"SSTA")] @@ -142,4 +144,19 @@ pub enum EventDataDetails { #[br(map(u8_to_usize))] overtaken_vehicle_index: usize, }, + /// Sent when safety car gets deployed. + /// Available from the 2024 format onwards. + #[br(magic = b"SCAR")] + SafetyCar { safety_car_type: SafetyCarType, event_type: SafetyCarEventType }, + /// Sent when two vehicles collide. + /// Available from the 2024 format onwards. + #[br(magic = b"COLL")] + Collision { + /// Index of the first vehicle involved in the collision. + #[br(map(u8_to_usize))] + vehicle1_index: usize, + /// Index of the second vehicle involved in the collision. + #[br(map(u8_to_usize))] + vehicle2_index: usize, + }, } diff --git a/src/packets/final_classification.rs b/src/packets/final_classification.rs index 1483c76..c48d125 100644 --- a/src/packets/final_classification.rs +++ b/src/packets/final_classification.rs @@ -4,17 +4,11 @@ use crate::constants::{ActualTyreCompound, ResultStatus, VisualTyreCompound}; use binrw::BinRead; use serde::{Deserialize, Serialize}; +const MAX_NUM_TYRE_STINTS: usize = 8; + #[non_exhaustive] -#[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)] -#[br( - little, - import(_packet_format: u16), - assert( - num_tyre_stints <= 8, - "Final classification entry has an invalid number of tyre stints: {}", - num_tyre_stints - ) -)] +#[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] +#[br(little, import(_packet_format: u16))] pub struct FinalClassificationData { /// Finishing position. pub position: u8, @@ -36,13 +30,26 @@ pub struct FinalClassificationData { pub penalties_time: u8, /// Number of penalties applied to this driver. pub num_penalties: u8, - /// Number of tyre stints (no greater than 8). - #[br(map(u8_to_usize))] + /// Number of tyre stints. + #[br( + map(u8_to_usize), + assert( + num_tyre_stints <= MAX_NUM_TYRE_STINTS, + "Final classification entry has an invalid number of tyre stints: {}", + num_tyre_stints + ) + )] pub num_tyre_stints: usize, /// Actual tyres used by the driver. - pub tyre_stints_actual: [ActualTyreCompound; 8], + /// Should have a size equal to `num_tyre_stints`. + #[br(count(num_tyre_stints), pad_after(MAX_NUM_TYRE_STINTS - num_tyre_stints))] + pub tyre_stints_actual: Vec, /// Visual tyres used by the driver. - pub tyre_stints_visual: [VisualTyreCompound; 8], + /// Should have a size equal to `num_tyre_stints`. + #[br(count(num_tyre_stints), pad_after(MAX_NUM_TYRE_STINTS - num_tyre_stints))] + pub tyre_stints_visual: Vec, /// The lap numbers the stints end on. - pub tyre_stints_end_laps: [u8; 8], + /// Should have a size equal to `num_tyre_stints`. + #[br(count(num_tyre_stints), pad_after(MAX_NUM_TYRE_STINTS - num_tyre_stints))] + pub tyre_stints_end_laps: Vec, } diff --git a/src/packets/lap.rs b/src/packets/lap.rs index 9901335..eeae897 100644 --- a/src/packets/lap.rs +++ b/src/packets/lap.rs @@ -21,26 +21,34 @@ pub struct LapData { pub last_lap_time_ms: u32, /// Current lap time in milliseconds. pub current_lap_time_ms: u32, - /// Current sector 1 time in milliseconds. - pub sector1_time_ms: u16, + /// Current sector 1 time millisecond part. + pub sector1_time_ms_part: u16, /// Sector 1 whole minute part. /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023))] - pub sector1_time_minutes: u8, - /// Current sector 2 time in milliseconds. - pub sector2_time_ms: u16, + pub sector1_time_minutes_part: u8, + /// Current sector 2 time millisecond part. + pub sector2_time_ms_part: u16, /// Sector 2 whole minute part. /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023))] - pub sector2_time_minutes: u8, + pub sector2_time_minutes_part: u8, /// Time delta to car in front in milliseconds. /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023))] - pub delta_to_car_in_front_ms: u16, + pub delta_to_car_in_front_ms_part: u16, + /// Time delta to car in front whole minute part. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub delta_to_car_in_front_minutes_part: u8, /// Time delta to race leader in milliseconds. /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023))] pub delta_to_race_leader_ms: u16, + /// Time delta to car in front whole minute part. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub delta_to_race_leader_minutes_part: u8, /// The distance the vehicle is around current lap in metres. /// It may be negative if the start/finish line hasn’t been crossed yet. pub lap_distance: f32, @@ -66,12 +74,6 @@ pub struct LapData { /// Accumulated time penalties to be added in seconds. pub penalties: u8, /// Accumulated number of warnings issued. - /// Available only in the 2022 format. - #[br(if(packet_format == 2022))] - pub warnings: u8, - /// Accumulated number of warnings issued. - /// Available from the 2023 format onwards. - #[br(if(packet_format >= 2023))] pub total_warnings: u8, /// Accumulated number of corner cutting warnings issued. /// Available from the 2023 format onwards. @@ -97,4 +99,13 @@ pub struct LapData { /// Whether the car should serve a penalty at this stop. #[br(try_map(u8_to_bool))] pub pit_stop_should_serve_pen: bool, + /// Fastest speed through speed trap for this car in kilometres per hour. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub speed_trap_fastest_speed: f32, + /// Number of the lap the fastest speed was achieved on + /// (255 means "not set") + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub speed_trap_fastest_lap: u8, } diff --git a/src/packets/lobby.rs b/src/packets/lobby.rs index 56b3119..63d220c 100644 --- a/src/packets/lobby.rs +++ b/src/packets/lobby.rs @@ -1,11 +1,13 @@ use super::{read_name, u8_to_bool}; -use crate::constants::{Nationality, Platform, ReadyStatus}; +use crate::constants::{Nationality, Platform, ReadyStatus, YourTelemetry}; use binrw::BinRead; use serde::{Deserialize, Serialize}; #[non_exhaustive] -#[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] +#[derive( + BinRead, Eq, PartialEq, Ord, PartialOrd, Clone, Debug, Serialize, Deserialize, +)] #[br(little, import(packet_format: u16))] pub struct LobbyInfoData { /// Whether the vehicle is controlled by AI. @@ -24,6 +26,18 @@ pub struct LobbyInfoData { pub name: String, /// Player's car number. pub car_number: u8, + /// The player's "Your Telemetry" visibility setting. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub your_telemetry: Option, + /// Whether the player has enabled the "Show online names" setting. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024), try_map(u8_to_bool))] + pub show_online_names: bool, + /// F1 World tech level. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub tech_level: u16, /// Readiness status. pub ready_status: ReadyStatus, } diff --git a/src/packets/mod.rs b/src/packets/mod.rs index 9cd1f82..a733c4f 100644 --- a/src/packets/mod.rs +++ b/src/packets/mod.rs @@ -10,6 +10,7 @@ pub mod motion; pub mod participants; pub mod session; pub mod session_history; +pub mod time_trial; pub mod tyre_sets; use crate::constants::{ @@ -39,6 +40,7 @@ use crate::packets::session_history::{ LapHistoryData, TyreStintHistoryData, LAP_HISTORY_RAW_SIZE, MAX_NUM_LAPS, MAX_NUM_TYRE_STINTS, }; +use crate::packets::time_trial::TimeTrialDataSet; use crate::packets::tyre_sets::{TyreSetData, NUM_TYRE_SETS}; use binrw::BinRead; @@ -54,7 +56,7 @@ pub struct F1PacketMotion { #[br(count(MAX_NUM_CARS), args{ inner: (packet_format,) })] pub car_motion_data: Vec, /// Extra player car only motion data. - /// Only in the 2022 format. + /// Available only in the 2022 format. #[br(if(packet_format == 2022))] pub motion_ex_data: Option, } @@ -370,7 +372,7 @@ pub struct F1PacketLap { /// Various notable events that happen during a session. #[non_exhaustive] #[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] -#[br(little, import(_packet_format: u16))] +#[br(little, import(packet_format: u16))] pub struct F1PacketEvent { /// 4-letter event code. #[br( @@ -379,6 +381,7 @@ pub struct F1PacketEvent { )] pub event_string_code: String, /// Extra data for this event. + #[br(args(packet_format))] pub event_details: EventDataDetails, } @@ -389,18 +392,18 @@ pub struct F1PacketEvent { little, import(packet_format: u16), assert( - num_cars <= MAX_NUM_CARS, + num_active_cars <= MAX_NUM_CARS, "Participants packet has an invalid number of cars: {}", - num_cars + num_active_cars ) )] pub struct F1PacketParticipants { /// Number of active cars in the session. #[br(map(u8_to_usize))] - pub num_cars: usize, + pub num_active_cars: usize, /// Data for all participants. /// Should have a size equal to `num_cars`. - #[br(count(num_cars), args{ inner: (packet_format,) })] + #[br(count(num_active_cars), args{ inner: (packet_format,) })] pub participants_data: Vec, } @@ -414,6 +417,10 @@ pub struct F1PacketCarSetups { /// Setup data for all cars on track. #[br(count(MAX_NUM_CARS), args{ inner: (packet_format,) })] pub car_setups_data: Vec, + /// Value of front wing after next pit stop - player only. + /// Available from the 2024 format onwards + #[br(if(packet_format >= 2024))] + pub next_front_wing_value: f32, } /// Telemetry (such as speed, DRS, throttle application, etc.) @@ -454,7 +461,7 @@ pub struct F1PacketCarStatus { #[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] #[br(little, import(packet_format: u16))] pub struct F1PacketFinalClassification { - /// Number of cars in the final classification (no greater than 22). + /// Number of cars in the final classification. #[br( map(u8_to_usize), assert( @@ -597,22 +604,44 @@ pub struct F1PacketMotionEx { /// See [`wheel_index`](mod@crate::constants::wheel_index) /// for wheel order. pub suspension_position: [f32; 4], - /// Velocities of suspension. + /// Velocity values of suspension for each wheel. /// See [`wheel_index`](mod@crate::constants::wheel_index) /// for wheel order. pub suspension_velocity: [f32; 4], - /// Accelerations of suspension in the following order: + /// Acceleration values of suspension for each wheel. /// See [`wheel_index`](mod@crate::constants::wheel_index) /// for wheel order. pub suspension_acceleration: [f32; 4], - /// Speed of each wheel in the following order: + /// Speed of each wheel. /// See [`wheel_index`](mod@crate::constants::wheel_index) /// for wheel order. pub wheel_speed: [f32; 4], - /// Slip ratio of each wheel in the following order: + /// Slip ratio for each wheel. /// See [`wheel_index`](mod@crate::constants::wheel_index) /// for wheel order. - pub wheel_slip: [f32; 4], + pub wheel_slip_ratio: [f32; 4], + /// Slip angles for each wheel. + /// See [`wheel_index`](mod@crate::constants::wheel_index) + /// for wheel order. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub wheel_slip_angle: [f32; 4], + /// Lateral forces for each wheel. + /// See [`wheel_index`](mod@crate::constants::wheel_index) + /// for wheel order. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub wheel_lat_force: [f32; 4], + /// Longitudinal forces for each wheel. + /// See [`wheel_index`](mod@crate::constants::wheel_index) + /// for wheel order. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub wheel_long_force: [f32; 4], + /// Height of centre of gravity above ground. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub height_of_cog_above_ground: f32, /// X velocity in local space. pub local_velocity_x: f32, /// Y velocity in local space. @@ -639,6 +668,42 @@ pub struct F1PacketMotionEx { /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023))] pub wheel_vert_force: [f32; 4], + /// Front plank edge height above road surface. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub front_aero_height: f32, + /// Rear plank edge height above road surface. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub rear_aero_height: f32, + /// Roll angle of the front suspension. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub front_roll_angle: f32, + /// Roll angle of the rear suspension. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub rear_roll_angle: f32, + /// Yaw angle of the chassis relative to the direction of motion - radians. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub chassis_yaw: f32, +} + +/// Extra information that's only relevant to time trial game mode. +/// Available from the 2024 format onwards. +#[non_exhaustive] +#[derive( + BinRead, Eq, PartialEq, Ord, PartialOrd, Clone, Debug, Serialize, Deserialize, +)] +#[br(little, import(_packet_format: u16))] +pub struct F1PacketTimeTrial { + /// Data set of player's best run this session. + pub player_session_best_data_set: TimeTrialDataSet, + /// Data set of player's personal best run. + pub personal_best_data_set: TimeTrialDataSet, + /// Data set of rival's best run. + pub rival_data_set: TimeTrialDataSet, } #[derive(Debug, PartialEq)] diff --git a/src/packets/participants.rs b/src/packets/participants.rs index 70750fa..561f8c2 100644 --- a/src/packets/participants.rs +++ b/src/packets/participants.rs @@ -5,34 +5,40 @@ use binrw::BinRead; use serde::{Deserialize, Serialize}; #[non_exhaustive] -#[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] +#[derive( + BinRead, Eq, PartialEq, Ord, PartialOrd, Clone, Debug, Serialize, Deserialize, +)] #[br(little, import(packet_format: u16))] pub struct ParticipantsData { - /// Whether the vehicle is controlled by AI + /// Whether the vehicle is controlled by AI. #[br(try_map(u8_to_bool))] pub ai_controlled: bool, - /// Driver's ID + /// Driver's ID. pub driver_id: u8, - /// Unique ID for network players + /// Unique ID for network players. pub network_id: u8, - /// Team's ID + /// Team's ID. pub team_id: u8, - /// Whether my team is being used + /// Whether my team is being used. #[br(try_map(u8_to_bool))] pub my_team: bool, - /// Race number of the car + /// Race number of the car. pub race_number: u8, - /// Driver's nationality + /// Driver's nationality. pub nationality: Nationality, - /// Driver's name + /// Driver's name. #[br(try_map(read_name))] pub name: String, - /// Player's UDP visibility setting + /// Player's UDP visibility setting. pub your_telemetry: Option, /// Whether this player's "show online names" setting is on. /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023), try_map(u8_to_bool))] pub show_online_names: bool, + /// F1 World tech level. + /// Available from the 2024 format onwards. + #[br(if(packet_format >= 2024))] + pub tech_level: u16, /// Player's platform. /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023))] diff --git a/src/packets/session.rs b/src/packets/session.rs index 8feb8d8..d937bce 100644 --- a/src/packets/session.rs +++ b/src/packets/session.rs @@ -29,7 +29,9 @@ pub struct MarshalZone { #[non_exhaustive] /// Weather forecast sample for a given session. -#[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)] +#[derive( + BinRead, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, +)] #[br( little, import(_packet_format: u16), diff --git a/src/packets/session_history.rs b/src/packets/session_history.rs index 20d0bdf..810bc6a 100644 --- a/src/packets/session_history.rs +++ b/src/packets/session_history.rs @@ -7,29 +7,30 @@ use serde::{Deserialize, Serialize}; pub(super) const MAX_NUM_LAPS: usize = 100; pub(super) const LAP_HISTORY_RAW_SIZE: usize = 14; pub(super) const MAX_NUM_TYRE_STINTS: usize = 8; -pub(super) const TYRE_STINT_RAW_SIZE: usize = 3; #[non_exhaustive] -#[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] +#[derive( + BinRead, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, +)] #[br(little, import(packet_format: u16))] pub struct LapHistoryData { /// Lap time in milliseconds. pub lap_time_ms: u32, - /// Sector 1 time in milliseconds. - pub sector1_time_ms: u16, - /// Sector 1 whole minute part + /// Sector 1 time milliseconds part. + pub sector1_time_ms_part: u16, + /// Sector 1 whole minute part. /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023))] - pub sector1_time_minutes: u8, - /// Sector 2 time in milliseconds. - pub sector2_time_ms: u16, - /// Sector 2 whole minute part + pub sector1_time_minutes_part: u8, + /// Sector 2 time milliseconds part. + pub sector2_time_ms_part: u16, + /// Sector 2 whole minute part. /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023))] - pub sector2_time_minutes: u8, - /// Sector 3 time in milliseconds. - pub sector3_time_ms: u16, - /// Sector 3 whole minute part + pub sector2_time_minutes_part: u8, + /// Sector 3 time milliseconds part. + pub sector3_time_ms_part: u16, + /// Sector 3 whole minute part. /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023))] pub sector3_time_minutes: u8, @@ -39,7 +40,9 @@ pub struct LapHistoryData { } #[non_exhaustive] -#[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] +#[derive( + BinRead, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, +)] #[br(little, import(_packet_format: u16))] pub struct TyreStintHistoryData { /// Lap the tyre usage ends on (255 if current tyre). diff --git a/src/packets/time_trial.rs b/src/packets/time_trial.rs new file mode 100644 index 0000000..8dedfa6 --- /dev/null +++ b/src/packets/time_trial.rs @@ -0,0 +1,42 @@ +use super::{u8_to_bool, u8_to_usize}; +use crate::constants::{GearboxAssist, TractionControl}; + +use binrw::BinRead; +use serde::{Deserialize, Serialize}; + +#[non_exhaustive] +#[derive( + BinRead, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, +)] +#[br(little, import(_packet_format: u16))] +pub struct TimeTrialDataSet { + /// Index of the car this data set relates to. + #[br(map(u8_to_usize))] + pub vehicle_index: usize, + /// Team's ID. + pub team_id: u8, + /// Lap time in milliseconds. + pub lap_time_ms: u32, + /// Sector 1 time in milliseconds. + pub sector1_time_ms: u32, + /// Sector 2 time in milliseconds. + pub sector2_time_ms: u32, + /// Sector 3 time in milliseconds. + pub sector3_time_ms: u32, + /// Type of traction control assist enabled. + pub traction_control: TractionControl, + /// Type of gearbox assist enabled. + pub gearbox_assist: GearboxAssist, + /// Whether ABS is enabled. + #[br(try_map(u8_to_bool))] + pub anti_lock_brakes: bool, + /// Whether equal car performance is enabled. + #[br(try_map(u8_to_bool))] + pub equal_car_performance: bool, + /// Whether custom setup is in use. + #[br(try_map(u8_to_bool))] + pub custom_setup: bool, + /// Whether this lap is valid. + #[br(try_map(u8_to_bool))] + pub valid: bool, +}