feat: add 2024 spec parser fields and constants

This commit is contained in:
Maciej Pędzich 2025-02-21 21:00:56 +01:00
parent d2ded9da51
commit edaef5b865
Signed by: maciejpedzich
GPG Key ID: CE4A303D84882F0D
15 changed files with 357 additions and 154 deletions

View File

@ -1001,3 +1001,27 @@ pub enum RedFlags {
Standard = 2, Standard = 2,
Increased = 3, 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,
}

View File

@ -6,7 +6,7 @@ use crate::packets::{
u8_to_usize, F1PacketCarDamage, F1PacketCarSetups, F1PacketCarStatus, u8_to_usize, F1PacketCarDamage, F1PacketCarSetups, F1PacketCarStatus,
F1PacketCarTelemetry, F1PacketEvent, F1PacketFinalClassification, F1PacketLap, F1PacketCarTelemetry, F1PacketEvent, F1PacketFinalClassification, F1PacketLap,
F1PacketLobbyInfo, F1PacketMotion, F1PacketMotionEx, F1PacketParticipants, F1PacketLobbyInfo, F1PacketMotion, F1PacketMotionEx, F1PacketParticipants,
F1PacketSession, F1PacketSessionHistory, F1PacketTyreSets, F1PacketSession, F1PacketSessionHistory, F1PacketTimeTrial, F1PacketTyreSets,
}; };
use binrw::io::Cursor; use binrw::io::Cursor;
@ -125,4 +125,8 @@ pub struct F1PacketBody {
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_id == PacketId::MotionEx), args(packet_format))] #[br(if(packet_id == PacketId::MotionEx), args(packet_format))]
pub motion_ex: Option<F1PacketMotionEx>, pub motion_ex: Option<F1PacketMotionEx>,
/// 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<F1PacketTimeTrial>,
} }

View File

@ -18,44 +18,44 @@ pub struct CarDamageData {
/// See [`wheel_index`](mod@crate::constants::wheel_index) /// See [`wheel_index`](mod@crate::constants::wheel_index)
/// for wheel order. /// for wheel order.
pub brakes_damage: [u8; 4], pub brakes_damage: [u8; 4],
/// Front left wing damage (percentage) /// Front left wing damage (percentage).
pub front_left_wing_damage: u8, pub front_left_wing_damage: u8,
/// Front right wing damage (percentage) /// Front right wing damage (percentage).
pub front_right_wing_damage: u8, pub front_right_wing_damage: u8,
/// Rear wing damage (percentage) /// Rear wing damage (percentage).
pub rear_wing_damage: u8, pub rear_wing_damage: u8,
/// Floor damage (percentage) /// Floor damage (percentage).
pub floor_damage: u8, pub floor_damage: u8,
/// Diffuser damage (percentage) /// Diffuser damage (percentage).
pub diffuser_damage: u8, pub diffuser_damage: u8,
/// Sidepod damage (percentage) /// Sidepod damage (percentage).
pub sidepod_damage: u8, pub sidepod_damage: u8,
/// Whether DRS has failed /// Whether DRS has failed.
#[br(try_map(u8_to_bool))] #[br(try_map(u8_to_bool))]
pub drs_fault: bool, pub drs_fault: bool,
/// Whether ERS has failed /// Whether ERS has failed.
#[br(try_map(u8_to_bool))] #[br(try_map(u8_to_bool))]
pub ers_fault: bool, pub ers_fault: bool,
/// Gearbox damage (percentage) /// Gearbox damage (percentage).
pub gearbox_damage: u8, pub gearbox_damage: u8,
/// Engine damage (percentage) /// Engine damage (percentage).
pub engine_damage: u8, pub engine_damage: u8,
/// Engine MGU-H wear (percentage) /// Engine MGU-H wear (percentage).
pub engine_mguh_wear: u8, pub engine_mguh_wear: u8,
/// Engine ES wear (percentage) /// Engine ES wear (percentage).
pub engine_es_wear: u8, pub engine_es_wear: u8,
/// Engine CE wear (percentage) /// Engine CE wear (percentage).
pub engine_ce_wear: u8, pub engine_ce_wear: u8,
/// Engine ICE wear (percentage) /// Engine ICE wear (percentage).
pub engine_ice_wear: u8, pub engine_ice_wear: u8,
/// Engine MGU-K wear (percentage) /// Engine MGU-K wear (percentage).
pub engine_mguk_wear: u8, pub engine_mguk_wear: u8,
/// Engine TC wear (percentage) /// Engine TC wear (percentage).
pub engine_tc_wear: u8, pub engine_tc_wear: u8,
/// Whether the engine has blown /// Whether the engine has blown.
#[br(try_map(u8_to_bool))] #[br(try_map(u8_to_bool))]
pub engine_blown: bool, pub engine_blown: bool,
/// Whether the engine has seized /// Whether the engine has seized.
#[br(try_map(u8_to_bool))] #[br(try_map(u8_to_bool))]
pub engine_seized: bool, pub engine_seized: bool,
} }

View File

@ -5,48 +5,48 @@ use serde::{Deserialize, Serialize};
#[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)] #[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)]
#[br(little, import(_packet_format: u16))] #[br(little, import(_packet_format: u16))]
pub struct CarSetupData { pub struct CarSetupData {
/// Front wing aero /// Front wing aero.
pub front_wing: u8, pub front_wing: u8,
/// Rear wing aero /// Rear wing aero.
pub rear_wing: u8, pub rear_wing: u8,
/// Differential adjustment on throttle (percentage) /// Differential adjustment on throttle (percentage).
pub on_throttle: u8, pub on_throttle: u8,
/// Differential adjustment off throttle (percentage) /// Differential adjustment off throttle (percentage).
pub off_throttle: u8, pub off_throttle: u8,
/// Front camber angle (suspension geometry) /// Front camber angle (suspension geometry).
pub front_camber: f32, pub front_camber: f32,
/// Rear camber angle (suspension geometry) /// Rear camber angle (suspension geometry).
pub rear_camber: f32, pub rear_camber: f32,
/// Front toe angle (suspension geometry) /// Front toe angle (suspension geometry).
pub front_toe: f32, pub front_toe: f32,
/// Rear toe angle (suspension geometry) /// Rear toe angle (suspension geometry).
pub rear_toe: f32, pub rear_toe: f32,
/// Front suspension /// Front suspension.
pub front_suspension: u8, pub front_suspension: u8,
/// Rear suspension /// Rear suspension.
pub rear_suspension: u8, pub rear_suspension: u8,
/// Front anti-roll bar /// Front anti-roll bar.
pub front_anti_roll_bar: u8, pub front_anti_roll_bar: u8,
/// Rear anti-roll bar /// Rear anti-roll bar.
pub rear_anti_roll_bar: u8, pub rear_anti_roll_bar: u8,
/// Front ride height /// Front ride height.
pub front_suspension_height: u8, pub front_suspension_height: u8,
/// Rear ride height /// Rear ride height.
pub rear_suspension_height: u8, pub rear_suspension_height: u8,
/// Brake pressure (percentage) /// Brake pressure (percentage).
pub brake_pressure: u8, pub brake_pressure: u8,
/// Brake bias /// Brake bias.
pub brake_bias: u8, pub brake_bias: u8,
/// Rear left tyre pressure /// Rear left tyre pressure.
pub rear_left_tyre_pressure: f32, pub rear_left_tyre_pressure: f32,
/// Rear right tyre pressure /// Rear right tyre pressure.
pub rear_right_tyre_pressure: f32, pub rear_right_tyre_pressure: f32,
/// Front left tyre pressure /// Front left tyre pressure.
pub front_left_tyre_pressure: f32, pub front_left_tyre_pressure: f32,
/// Front right tyre pressure /// Front right tyre pressure.
pub front_right_tyre_pressure: f32, pub front_right_tyre_pressure: f32,
/// Ballast /// Ballast.
pub ballast: u8, pub ballast: u8,
/// Fuel load /// Fuel load.
pub fuel_load: f32, pub fuel_load: f32,
} }

View File

@ -9,15 +9,7 @@ use serde::{Deserialize, Serialize};
#[non_exhaustive] #[non_exhaustive]
#[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)] #[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)]
#[br( #[br(little, import(packet_format: u16))]
little,
import(packet_format: u16),
assert(
max_gears <= 9,
"Car status entry has an invalid max number of gears: {}",
max_gears
)
)]
pub struct CarStatusData { pub struct CarStatusData {
/// How much traction control is enabled. /// How much traction control is enabled.
pub traction_control: TractionControl, pub traction_control: TractionControl,
@ -42,6 +34,13 @@ pub struct CarStatusData {
/// Car's idle RPM. /// Car's idle RPM.
pub idle_rpm: u16, pub idle_rpm: u16,
/// Maximum number of gears. /// 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, pub max_gears: u8,
/// Whether DRS can be used (might be unknown). /// Whether DRS can be used (might be unknown).
pub drs_allowed: DrsAllowed, pub drs_allowed: DrsAllowed,

View File

@ -6,52 +6,54 @@ use serde::{Deserialize, Serialize};
#[non_exhaustive] #[non_exhaustive]
#[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)] #[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)]
#[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( #[br(
little,
import(_packet_format: u16),
assert( assert(
(0.0..=1.0).contains(&throttle), (0.0..=1.0).contains(&throttle),
"Car telemetry entry has an invalid throttle value: {}", "Car telemetry entry has an invalid throttle value: {}",
throttle throttle
), ),
)]
pub throttle: f32,
/// Steering lock. Value in range `(-1.0..=1.0)`.
#[br(
assert( assert(
(-1.0..=1.0).contains(&steer), (-1.0..=1.0).contains(&steer),
"Car telemetry entry has an invalid steering lock value: {}", "Car telemetry entry has an invalid steering lock value: {}",
steer steer
), ),
)]
pub steer: f32,
/// Amount of brake applied. Value in range `(0.0..=1.0)`.
#[br(
assert( assert(
(0.0..=1.0).contains(&brake), (0.0..=1.0).contains(&brake),
"Car telemetry entry has an invalid brake value: {}", "Car telemetry entry has an invalid brake value: {}",
brake brake
), ),
)]
pub brake: f32,
/// Amount of clutch applied (percentage).
#[br(
assert( assert(
clutch <= 100, clutch <= 100,
"Car telemetry entry has an invalid clutch value: {}", "Car telemetry entry has an invalid clutch value: {}",
clutch clutch
), ),
)]
pub clutch: u8,
/// Selected gear. Neutral = 0, reverse = -1.
#[br(
assert( assert(
(-1..=8).contains(&gear), (-1..=8).contains(&gear),
"Car telemetry entry has an invalid gear value: {}", "Car telemetry entry has an invalid gear value: {}",
gear gear
), ),
assert(
rev_lights_percent <= 100,
"Car telemetry entry has an invalid rev lights percentage: {}",
rev_lights_percent
),
)] )]
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)`.
pub throttle: f32,
/// Steering lock. Value in range `(-1.0..=1.0)`.
pub steer: f32,
/// Amount of brake applied. Value in range `(0.0..=1.0)`.
pub brake: f32,
/// Amount of clutch applied (percentage).
pub clutch: u8,
/// Selected gear. Neutral = 0, reverse = -1.
pub gear: i8, pub gear: i8,
/// Engine RPM. /// Engine RPM.
pub engine_rpm: u16, pub engine_rpm: u16,
@ -59,6 +61,13 @@ pub struct CarTelemetryData {
#[br(try_map(u8_to_bool))] #[br(try_map(u8_to_bool))]
pub drs_enabled: bool, pub drs_enabled: bool,
/// Rev lights indicator (percentage). /// 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, pub rev_lights_percent: u8,
/// Bitmap of active rev lights. /// Bitmap of active rev lights.
#[br(map(RevLights::from_bits_truncate))] #[br(map(RevLights::from_bits_truncate))]

View File

@ -1,12 +1,14 @@
use super::{u8_to_bool, u8_to_usize}; 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 binrw::BinRead;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[non_exhaustive] #[non_exhaustive]
#[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] #[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)]
#[br(little)] #[br(little, import(_packet_format: u16))]
pub enum EventDataDetails { pub enum EventDataDetails {
/// Sent when the session starts. /// Sent when the session starts.
#[br(magic = b"SSTA")] #[br(magic = b"SSTA")]
@ -142,4 +144,19 @@ pub enum EventDataDetails {
#[br(map(u8_to_usize))] #[br(map(u8_to_usize))]
overtaken_vehicle_index: 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,
},
} }

View File

@ -4,17 +4,11 @@ use crate::constants::{ActualTyreCompound, ResultStatus, VisualTyreCompound};
use binrw::BinRead; use binrw::BinRead;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
const MAX_NUM_TYRE_STINTS: usize = 8;
#[non_exhaustive] #[non_exhaustive]
#[derive(BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize)] #[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)]
#[br( #[br(little, import(_packet_format: u16))]
little,
import(_packet_format: u16),
assert(
num_tyre_stints <= 8,
"Final classification entry has an invalid number of tyre stints: {}",
num_tyre_stints
)
)]
pub struct FinalClassificationData { pub struct FinalClassificationData {
/// Finishing position. /// Finishing position.
pub position: u8, pub position: u8,
@ -36,13 +30,26 @@ pub struct FinalClassificationData {
pub penalties_time: u8, pub penalties_time: u8,
/// Number of penalties applied to this driver. /// Number of penalties applied to this driver.
pub num_penalties: u8, pub num_penalties: u8,
/// Number of tyre stints (no greater than 8). /// Number of tyre stints.
#[br(map(u8_to_usize))] #[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, pub num_tyre_stints: usize,
/// Actual tyres used by the driver. /// 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<ActualTyreCompound>,
/// Visual tyres used by the driver. /// 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<VisualTyreCompound>,
/// The lap numbers the stints end on. /// 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<u8>,
} }

View File

@ -21,26 +21,34 @@ pub struct LapData {
pub last_lap_time_ms: u32, pub last_lap_time_ms: u32,
/// Current lap time in milliseconds. /// Current lap time in milliseconds.
pub current_lap_time_ms: u32, pub current_lap_time_ms: u32,
/// Current sector 1 time in milliseconds. /// Current sector 1 time millisecond part.
pub sector1_time_ms: u16, pub sector1_time_ms_part: u16,
/// Sector 1 whole minute part. /// Sector 1 whole minute part.
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_format >= 2023))] #[br(if(packet_format >= 2023))]
pub sector1_time_minutes: u8, pub sector1_time_minutes_part: u8,
/// Current sector 2 time in milliseconds. /// Current sector 2 time millisecond part.
pub sector2_time_ms: u16, pub sector2_time_ms_part: u16,
/// Sector 2 whole minute part. /// Sector 2 whole minute part.
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_format >= 2023))] #[br(if(packet_format >= 2023))]
pub sector2_time_minutes: u8, pub sector2_time_minutes_part: u8,
/// Time delta to car in front in milliseconds. /// Time delta to car in front in milliseconds.
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_format >= 2023))] #[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. /// Time delta to race leader in milliseconds.
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_format >= 2023))] #[br(if(packet_format >= 2023))]
pub delta_to_race_leader_ms: u16, 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. /// The distance the vehicle is around current lap in metres.
/// It may be negative if the start/finish line hasnt been crossed yet. /// It may be negative if the start/finish line hasnt been crossed yet.
pub lap_distance: f32, pub lap_distance: f32,
@ -66,12 +74,6 @@ pub struct LapData {
/// Accumulated time penalties to be added in seconds. /// Accumulated time penalties to be added in seconds.
pub penalties: u8, pub penalties: u8,
/// Accumulated number of warnings issued. /// 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, pub total_warnings: u8,
/// Accumulated number of corner cutting warnings issued. /// Accumulated number of corner cutting warnings issued.
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
@ -97,4 +99,13 @@ pub struct LapData {
/// Whether the car should serve a penalty at this stop. /// Whether the car should serve a penalty at this stop.
#[br(try_map(u8_to_bool))] #[br(try_map(u8_to_bool))]
pub pit_stop_should_serve_pen: 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,
} }

View File

@ -1,11 +1,13 @@
use super::{read_name, u8_to_bool}; use super::{read_name, u8_to_bool};
use crate::constants::{Nationality, Platform, ReadyStatus}; use crate::constants::{Nationality, Platform, ReadyStatus, YourTelemetry};
use binrw::BinRead; use binrw::BinRead;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[non_exhaustive] #[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))] #[br(little, import(packet_format: u16))]
pub struct LobbyInfoData { pub struct LobbyInfoData {
/// Whether the vehicle is controlled by AI. /// Whether the vehicle is controlled by AI.
@ -24,6 +26,18 @@ pub struct LobbyInfoData {
pub name: String, pub name: String,
/// Player's car number. /// Player's car number.
pub car_number: u8, 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<YourTelemetry>,
/// 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. /// Readiness status.
pub ready_status: ReadyStatus, pub ready_status: ReadyStatus,
} }

View File

@ -10,6 +10,7 @@ pub mod motion;
pub mod participants; pub mod participants;
pub mod session; pub mod session;
pub mod session_history; pub mod session_history;
pub mod time_trial;
pub mod tyre_sets; pub mod tyre_sets;
use crate::constants::{ use crate::constants::{
@ -39,6 +40,7 @@ use crate::packets::session_history::{
LapHistoryData, TyreStintHistoryData, LAP_HISTORY_RAW_SIZE, MAX_NUM_LAPS, LapHistoryData, TyreStintHistoryData, LAP_HISTORY_RAW_SIZE, MAX_NUM_LAPS,
MAX_NUM_TYRE_STINTS, MAX_NUM_TYRE_STINTS,
}; };
use crate::packets::time_trial::TimeTrialDataSet;
use crate::packets::tyre_sets::{TyreSetData, NUM_TYRE_SETS}; use crate::packets::tyre_sets::{TyreSetData, NUM_TYRE_SETS};
use binrw::BinRead; use binrw::BinRead;
@ -54,7 +56,7 @@ pub struct F1PacketMotion {
#[br(count(MAX_NUM_CARS), args{ inner: (packet_format,) })] #[br(count(MAX_NUM_CARS), args{ inner: (packet_format,) })]
pub car_motion_data: Vec<CarMotionData>, pub car_motion_data: Vec<CarMotionData>,
/// Extra player car only motion data. /// Extra player car only motion data.
/// Only in the 2022 format. /// Available only in the 2022 format.
#[br(if(packet_format == 2022))] #[br(if(packet_format == 2022))]
pub motion_ex_data: Option<F1PacketMotionEx>, pub motion_ex_data: Option<F1PacketMotionEx>,
} }
@ -370,7 +372,7 @@ pub struct F1PacketLap {
/// Various notable events that happen during a session. /// Various notable events that happen during a session.
#[non_exhaustive] #[non_exhaustive]
#[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] #[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)]
#[br(little, import(_packet_format: u16))] #[br(little, import(packet_format: u16))]
pub struct F1PacketEvent { pub struct F1PacketEvent {
/// 4-letter event code. /// 4-letter event code.
#[br( #[br(
@ -379,6 +381,7 @@ pub struct F1PacketEvent {
)] )]
pub event_string_code: String, pub event_string_code: String,
/// Extra data for this event. /// Extra data for this event.
#[br(args(packet_format))]
pub event_details: EventDataDetails, pub event_details: EventDataDetails,
} }
@ -389,18 +392,18 @@ pub struct F1PacketEvent {
little, little,
import(packet_format: u16), import(packet_format: u16),
assert( assert(
num_cars <= MAX_NUM_CARS, num_active_cars <= MAX_NUM_CARS,
"Participants packet has an invalid number of cars: {}", "Participants packet has an invalid number of cars: {}",
num_cars num_active_cars
) )
)] )]
pub struct F1PacketParticipants { pub struct F1PacketParticipants {
/// Number of active cars in the session. /// Number of active cars in the session.
#[br(map(u8_to_usize))] #[br(map(u8_to_usize))]
pub num_cars: usize, pub num_active_cars: usize,
/// Data for all participants. /// Data for all participants.
/// Should have a size equal to `num_cars`. /// 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<ParticipantsData>, pub participants_data: Vec<ParticipantsData>,
} }
@ -414,6 +417,10 @@ pub struct F1PacketCarSetups {
/// Setup data for all cars on track. /// Setup data for all cars on track.
#[br(count(MAX_NUM_CARS), args{ inner: (packet_format,) })] #[br(count(MAX_NUM_CARS), args{ inner: (packet_format,) })]
pub car_setups_data: Vec<CarSetupData>, pub car_setups_data: Vec<CarSetupData>,
/// 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.) /// Telemetry (such as speed, DRS, throttle application, etc.)
@ -454,7 +461,7 @@ pub struct F1PacketCarStatus {
#[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] #[derive(BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)]
#[br(little, import(packet_format: u16))] #[br(little, import(packet_format: u16))]
pub struct F1PacketFinalClassification { pub struct F1PacketFinalClassification {
/// Number of cars in the final classification (no greater than 22). /// Number of cars in the final classification.
#[br( #[br(
map(u8_to_usize), map(u8_to_usize),
assert( assert(
@ -597,22 +604,44 @@ pub struct F1PacketMotionEx {
/// See [`wheel_index`](mod@crate::constants::wheel_index) /// See [`wheel_index`](mod@crate::constants::wheel_index)
/// for wheel order. /// for wheel order.
pub suspension_position: [f32; 4], pub suspension_position: [f32; 4],
/// Velocities of suspension. /// Velocity values of suspension for each wheel.
/// See [`wheel_index`](mod@crate::constants::wheel_index) /// See [`wheel_index`](mod@crate::constants::wheel_index)
/// for wheel order. /// for wheel order.
pub suspension_velocity: [f32; 4], 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) /// See [`wheel_index`](mod@crate::constants::wheel_index)
/// for wheel order. /// for wheel order.
pub suspension_acceleration: [f32; 4], 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) /// See [`wheel_index`](mod@crate::constants::wheel_index)
/// for wheel order. /// for wheel order.
pub wheel_speed: [f32; 4], 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) /// See [`wheel_index`](mod@crate::constants::wheel_index)
/// for wheel order. /// 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. /// X velocity in local space.
pub local_velocity_x: f32, pub local_velocity_x: f32,
/// Y velocity in local space. /// Y velocity in local space.
@ -639,6 +668,42 @@ pub struct F1PacketMotionEx {
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_format >= 2023))] #[br(if(packet_format >= 2023))]
pub wheel_vert_force: [f32; 4], 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)] #[derive(Debug, PartialEq)]

View File

@ -5,34 +5,40 @@ use binrw::BinRead;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[non_exhaustive] #[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))] #[br(little, import(packet_format: u16))]
pub struct ParticipantsData { pub struct ParticipantsData {
/// Whether the vehicle is controlled by AI /// Whether the vehicle is controlled by AI.
#[br(try_map(u8_to_bool))] #[br(try_map(u8_to_bool))]
pub ai_controlled: bool, pub ai_controlled: bool,
/// Driver's ID /// Driver's ID.
pub driver_id: u8, pub driver_id: u8,
/// Unique ID for network players /// Unique ID for network players.
pub network_id: u8, pub network_id: u8,
/// Team's ID /// Team's ID.
pub team_id: u8, pub team_id: u8,
/// Whether my team is being used /// Whether my team is being used.
#[br(try_map(u8_to_bool))] #[br(try_map(u8_to_bool))]
pub my_team: bool, pub my_team: bool,
/// Race number of the car /// Race number of the car.
pub race_number: u8, pub race_number: u8,
/// Driver's nationality /// Driver's nationality.
pub nationality: Nationality, pub nationality: Nationality,
/// Driver's name /// Driver's name.
#[br(try_map(read_name))] #[br(try_map(read_name))]
pub name: String, pub name: String,
/// Player's UDP visibility setting /// Player's UDP visibility setting.
pub your_telemetry: Option<YourTelemetry>, pub your_telemetry: Option<YourTelemetry>,
/// Whether this player's "show online names" setting is on. /// Whether this player's "show online names" setting is on.
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_format >= 2023), try_map(u8_to_bool))] #[br(if(packet_format >= 2023), try_map(u8_to_bool))]
pub show_online_names: 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. /// Player's platform.
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_format >= 2023))] #[br(if(packet_format >= 2023))]

View File

@ -29,7 +29,9 @@ pub struct MarshalZone {
#[non_exhaustive] #[non_exhaustive]
/// Weather forecast sample for a given session. /// 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( #[br(
little, little,
import(_packet_format: u16), import(_packet_format: u16),

View File

@ -7,29 +7,30 @@ use serde::{Deserialize, Serialize};
pub(super) const MAX_NUM_LAPS: usize = 100; pub(super) const MAX_NUM_LAPS: usize = 100;
pub(super) const LAP_HISTORY_RAW_SIZE: usize = 14; pub(super) const LAP_HISTORY_RAW_SIZE: usize = 14;
pub(super) const MAX_NUM_TYRE_STINTS: usize = 8; pub(super) const MAX_NUM_TYRE_STINTS: usize = 8;
pub(super) const TYRE_STINT_RAW_SIZE: usize = 3;
#[non_exhaustive] #[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))] #[br(little, import(packet_format: u16))]
pub struct LapHistoryData { pub struct LapHistoryData {
/// Lap time in milliseconds. /// Lap time in milliseconds.
pub lap_time_ms: u32, pub lap_time_ms: u32,
/// Sector 1 time in milliseconds. /// Sector 1 time milliseconds part.
pub sector1_time_ms: u16, pub sector1_time_ms_part: u16,
/// Sector 1 whole minute part /// Sector 1 whole minute part.
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_format >= 2023))] #[br(if(packet_format >= 2023))]
pub sector1_time_minutes: u8, pub sector1_time_minutes_part: u8,
/// Sector 2 time in milliseconds. /// Sector 2 time milliseconds part.
pub sector2_time_ms: u16, pub sector2_time_ms_part: u16,
/// Sector 2 whole minute part /// Sector 2 whole minute part.
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_format >= 2023))] #[br(if(packet_format >= 2023))]
pub sector2_time_minutes: u8, pub sector2_time_minutes_part: u8,
/// Sector 3 time in milliseconds. /// Sector 3 time milliseconds part.
pub sector3_time_ms: u16, pub sector3_time_ms_part: u16,
/// Sector 3 whole minute part /// Sector 3 whole minute part.
/// Available from the 2023 format onwards. /// Available from the 2023 format onwards.
#[br(if(packet_format >= 2023))] #[br(if(packet_format >= 2023))]
pub sector3_time_minutes: u8, pub sector3_time_minutes: u8,
@ -39,7 +40,9 @@ pub struct LapHistoryData {
} }
#[non_exhaustive] #[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))] #[br(little, import(_packet_format: u16))]
pub struct TyreStintHistoryData { pub struct TyreStintHistoryData {
/// Lap the tyre usage ends on (255 if current tyre). /// Lap the tyre usage ends on (255 if current tyre).

42
src/packets/time_trial.rs Normal file
View File

@ -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,
}