diff --git a/.editorconfig b/.editorconfig
index ed2d0ac..f8f556e 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -228,10 +228,12 @@ dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
csharp_style_prefer_primary_constructors = true:suggestion
+csharp_prefer_system_threading_lock = true:suggestion
[*.{cs,vb}]
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
+indent_style = tab
indent_size = 4
end_of_line = crlf
dotnet_style_coalesce_expression = true:warning
diff --git a/F1Game.UDP.Benchamrks/F1Game.UDP.Benchmarks.csproj b/F1Game.UDP.Benchamrks/F1Game.UDP.Benchmarks.csproj
index 842dcdf..0d53da2 100644
--- a/F1Game.UDP.Benchamrks/F1Game.UDP.Benchmarks.csproj
+++ b/F1Game.UDP.Benchamrks/F1Game.UDP.Benchmarks.csproj
@@ -2,10 +2,11 @@
Exe
- net8.0
+ net8.0;net9.0
enable
enable
false
+ latest
diff --git a/F1Game.UDP.Benchamrks/Program.cs b/F1Game.UDP.Benchamrks/Program.cs
index 2266826..1233a2a 100644
--- a/F1Game.UDP.Benchamrks/Program.cs
+++ b/F1Game.UDP.Benchamrks/Program.cs
@@ -4,7 +4,8 @@
using BenchmarkDotNet.Running;
var config = DefaultConfig.Instance
- .AddJob(Job.Default.WithId("NET8").WithRuntime(CoreRuntime.Core80));
+ .AddJob(Job.Default.WithId("NET8").WithRuntime(CoreRuntime.Core80))
+ .AddJob(Job.Default.WithId("NET9").WithRuntime(CoreRuntime.Core90));
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly)
.Run(args, config);
diff --git a/F1Game.UDP.Benchamrks/ThirdPartyComparisonBenchmark.cs b/F1Game.UDP.Benchamrks/ThirdPartyComparisonBenchmark.cs
index 9da6f94..e90a71c 100644
--- a/F1Game.UDP.Benchamrks/ThirdPartyComparisonBenchmark.cs
+++ b/F1Game.UDP.Benchamrks/ThirdPartyComparisonBenchmark.cs
@@ -77,7 +77,9 @@ public Packet ReadF1Simracing()
static void SetupCarTelemetryPacket(byte[] data, Random random)
{
- var packet = data.ToPacket().CarTelemetryDataPacket;
+ if (!data.ToPacket().TryGetCarTelemetryDataPacket(out var packet))
+ return;
+
var updatedPacket = packet with
{
CarTelemetryData = packet.CarTelemetryData.AsEnumerable().Select(x => x with
@@ -93,7 +95,9 @@ static void SetupCarTelemetryPacket(byte[] data, Random random)
static void SetupCarStatusPacket(byte[] data, Random random)
{
- var packet = data.ToPacket().CarStatusDataPacket;
+ if (!data.ToPacket().TryGetCarStatusDataPacket(out var packet))
+ return;
+
var updatedPacket = packet with
{
CarStatusData = packet.CarStatusData.AsEnumerable().Select(x => x with
@@ -113,7 +117,9 @@ static void SetupEventPacket(byte[] data)
static void SetupSessionPacket(byte[] data, Random random)
{
- var packet = data.ToPacket().SessionDataPacket;
+ if (!data.ToPacket().TryGetSessionDataPacket(out var packet))
+ return;
+
var updatedPacket = packet with
{
AirTemperature = (sbyte)random.Next(127),
diff --git a/F1Game.UDP.Tests/F1Game.UDP.Tests.csproj b/F1Game.UDP.Tests/F1Game.UDP.Tests.csproj
index cbacf07..4ed0551 100644
--- a/F1Game.UDP.Tests/F1Game.UDP.Tests.csproj
+++ b/F1Game.UDP.Tests/F1Game.UDP.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net8.0;net9.0
enable
enable
false
diff --git a/F1Game.UDP.Tests/PacketReaderFixture.cs b/F1Game.UDP.Tests/PacketReaderFixture.cs
index 66abb85..38f12ae 100644
--- a/F1Game.UDP.Tests/PacketReaderFixture.cs
+++ b/F1Game.UDP.Tests/PacketReaderFixture.cs
@@ -7,6 +7,8 @@
using F1Game.UDP.Internal;
using F1Game.UDP.Packets;
+using AwesomeAssertions.Equivalency;
+
namespace F1Game.UDP.Tests;
[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
@@ -75,9 +77,9 @@ public void ReadCarDamageDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -91,9 +93,9 @@ public void ReadCarSetupDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -107,9 +109,9 @@ public void ReadCarStatusDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -123,9 +125,9 @@ public void ReadCarTelemetryDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[TestCase(EventType.ButtonStatus)]
@@ -178,9 +180,9 @@ public void ReadEventDataPacket(EventType eventType)
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -201,9 +203,9 @@ public void ReadFinalClassificationDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -217,9 +219,9 @@ public void ReadLapDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -238,9 +240,9 @@ public void ReadLobbyInfoDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -254,9 +256,9 @@ public void ReadMotionDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -269,9 +271,9 @@ public void ReadMotionExDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -290,9 +292,9 @@ public void ReadParticipantsDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -308,9 +310,9 @@ public void ReadSessionDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -325,9 +327,9 @@ public void ReadSessionHistoryDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -341,9 +343,9 @@ public void ReadTyreSetsDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
[Test]
@@ -355,9 +357,9 @@ public void ReadTimeTrialDataPacket()
var writer = new BytesWriter(bytes);
writer.Write(packet);
- bytes.ToPacket().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithReader().Should().BeEquivalentTo(packet);
- bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet);
+ bytes.ToPacket().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithReader().Should().BeEquivalentTo(packet, Configure);
+ bytes.ToPacketWithMarshal().Should().BeEquivalentTo(packet, Configure);
}
IPostprocessComposer BuildPacket() where T : IHaveHeader, new()
@@ -388,4 +390,7 @@ public void ReadTimeTrialDataPacket()
return fixture.Build()
.With(x => x.Header, header);
}
+
+ static EquivalencyOptions Configure(EquivalencyOptions options)
+ => options.IncludingInternalFields();
}
diff --git a/F1Game.UDP/Events/EventDetails.cs b/F1Game.UDP/Events/EventDetails.cs
index 1aaba90..b57ae4e 100644
--- a/F1Game.UDP/Events/EventDetails.cs
+++ b/F1Game.UDP/Events/EventDetails.cs
@@ -1,51 +1,190 @@
namespace F1Game.UDP.Events;
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 26)]
-public readonly record struct EventDetails
+public readonly record struct EventDetails : IByteWritable
{
[field: FieldOffset(0)]
public EventType EventType { get; init; } // Event string code, see below 4 chars
[field: FieldOffset(4)]
- public ButtonsEvent ButtonsEvent { get; init; }
+ private readonly ButtonsEvent buttonsEvent;
[field: FieldOffset(4)]
- public DriveThroughPenaltyServedEvent DriveThroughPenaltyServedEvent { get; init; }
+ private readonly DriveThroughPenaltyServedEvent driveThroughPenaltyServedEvent;
[field: FieldOffset(4)]
- public FastestLapEvent FastestLapEvent { get; init; }
+ private readonly FastestLapEvent fastestLapEvent;
[field: FieldOffset(4)]
- public FlashbackEvent FlashbackEvent { get; init; }
+ private readonly FlashbackEvent flashbackEvent;
[field: FieldOffset(4)]
- public OvertakeEvent OvertakeEvent { get; init; }
+ private readonly OvertakeEvent overtakeEvent;
[field: FieldOffset(4)]
- public PenaltyEvent PenaltyEvent { get; init; }
+ private readonly PenaltyEvent penaltyEvent;
[field: FieldOffset(4)]
- public RaceWinnerEvent RaceWinnerEvent { get; init; }
+ private readonly RaceWinnerEvent raceWinnerEvent;
[field: FieldOffset(4)]
- public RetirementEvent RetirementEvent { get; init; }
+ private readonly RetirementEvent retirementEvent;
[field: FieldOffset(4)]
- public SpeedTrapEvent SpeedTrapEvent { get; init; }
+ private readonly SpeedTrapEvent speedTrapEvent;
[field: FieldOffset(4)]
- public StartLightsEvent StartLightsEvent { get; init; }
+ private readonly StartLightsEvent startLightsEvent;
[field: FieldOffset(4)]
- public StopGoPenaltyServedEvent StopGoPenaltyServedEvent { get; init; }
+ private readonly StopGoPenaltyServedEvent stopGoPenaltyServedEvent;
[field: FieldOffset(4)]
- public TeamMateInPitsEvent TeamMateInPitsEvent { get; init; }
+ private readonly TeamMateInPitsEvent teamMateInPitsEvent;
[field: FieldOffset(4)]
- public CollisionEvent CollisionEvent { get; init; }
+ private readonly CollisionEvent collisionEvent;
[field: FieldOffset(4)]
- public SafetyCarEvent SafetyCarEvent { get; init; }
+ private readonly SafetyCarEvent safetyCarEvent;
- public static implicit operator EventDetails(ButtonsEvent buttonsEvent) => new() { EventType = EventType.ButtonStatus, ButtonsEvent = buttonsEvent };
- public static implicit operator EventDetails(DriveThroughPenaltyServedEvent driveThroughPenaltyServedEvent) => new() { EventType = EventType.DriveThroughServed, DriveThroughPenaltyServedEvent = driveThroughPenaltyServedEvent };
- public static implicit operator EventDetails(FastestLapEvent fastestLapEvent) => new() { EventType = EventType.FastestLap, FastestLapEvent = fastestLapEvent };
- public static implicit operator EventDetails(FlashbackEvent flashbackEvent) => new() { EventType = EventType.Flashback, FlashbackEvent = flashbackEvent };
- public static implicit operator EventDetails(OvertakeEvent overtakeEvent) => new() { EventType = EventType.Overtake, OvertakeEvent = overtakeEvent };
- public static implicit operator EventDetails(PenaltyEvent penaltyEvent) => new() { EventType = EventType.PenaltyIssued, PenaltyEvent = penaltyEvent };
- public static implicit operator EventDetails(RaceWinnerEvent raceWinnerEvent) => new() { EventType = EventType.RaceWinner, RaceWinnerEvent = raceWinnerEvent };
- public static implicit operator EventDetails(RetirementEvent retirementEvent) => new() { EventType = EventType.Retirement, RetirementEvent = retirementEvent };
- public static implicit operator EventDetails(SpeedTrapEvent speedTrapEvent) => new() { EventType = EventType.SpeedTrapTriggered, SpeedTrapEvent = speedTrapEvent };
- public static implicit operator EventDetails(StartLightsEvent startLightsEvent) => new() { EventType = EventType.StartLights, StartLightsEvent = startLightsEvent };
- public static implicit operator EventDetails(StopGoPenaltyServedEvent stopGoPenaltyServedEvent) => new() { EventType = EventType.StopGoServed, StopGoPenaltyServedEvent = stopGoPenaltyServedEvent };
- public static implicit operator EventDetails(TeamMateInPitsEvent teamMateInPitsEvent) => new() { EventType = EventType.TeamMateInPits, TeamMateInPitsEvent = teamMateInPitsEvent };
- public static implicit operator EventDetails(CollisionEvent collisionEvent) => new() { EventType = EventType.Collision, CollisionEvent = collisionEvent };
- public static implicit operator EventDetails(SafetyCarEvent safetyCarEvent) => new() { EventType = EventType.SafetyCar, SafetyCarEvent = safetyCarEvent };
+ public EventDetails(ButtonsEvent buttonsEvent) => (this.buttonsEvent, EventType) = (buttonsEvent, EventType.ButtonStatus);
+ public EventDetails(DriveThroughPenaltyServedEvent driveThroughPenaltyServedEvent) => (this.driveThroughPenaltyServedEvent, EventType) = (driveThroughPenaltyServedEvent, EventType.DriveThroughServed);
+ public EventDetails(FastestLapEvent fastestLapEvent) => (this.fastestLapEvent, EventType) = (fastestLapEvent, EventType.FastestLap);
+ public EventDetails(FlashbackEvent flashbackEvent) => (this.flashbackEvent, EventType) = (flashbackEvent, EventType.Flashback);
+ public EventDetails(OvertakeEvent overtakeEvent) => (this.overtakeEvent, EventType) = (overtakeEvent, EventType.Overtake);
+ public EventDetails(PenaltyEvent penaltyEvent) => (this.penaltyEvent, EventType) = (penaltyEvent, EventType.PenaltyIssued);
+ public EventDetails(RaceWinnerEvent raceWinnerEvent) => (this.raceWinnerEvent, EventType) = (raceWinnerEvent, EventType.RaceWinner);
+ public EventDetails(RetirementEvent retirementEvent) => (this.retirementEvent, EventType) = (retirementEvent, EventType.Retirement);
+ public EventDetails(SpeedTrapEvent speedTrapEvent) => (this.speedTrapEvent, EventType) = (speedTrapEvent, EventType.SpeedTrapTriggered);
+ public EventDetails(StartLightsEvent startLightsEvent) => (this.startLightsEvent, EventType) = (startLightsEvent, EventType.StartLights);
+ public EventDetails(StopGoPenaltyServedEvent stopGoPenaltyServedEvent) => (this.stopGoPenaltyServedEvent, EventType) = (stopGoPenaltyServedEvent, EventType.StopGoServed);
+ public EventDetails(TeamMateInPitsEvent teamMateInPitsEvent) => (this.teamMateInPitsEvent, EventType) = (teamMateInPitsEvent, EventType.TeamMateInPits);
+ public EventDetails(CollisionEvent collisionEvent) => (this.collisionEvent, EventType) = (collisionEvent, EventType.Collision);
+ public EventDetails(SafetyCarEvent safetyCarEvent) => (this.safetyCarEvent, EventType) = (safetyCarEvent, EventType.SafetyCar);
+
+ public bool TryGetButtonsEvent(out ButtonsEvent buttonsEvent)
+ {
+ var isRightEvent = EventType == EventType.ButtonStatus;
+ buttonsEvent = isRightEvent ? this.buttonsEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetDriveThroughPenaltyServedEvent(out DriveThroughPenaltyServedEvent driveThroughPenaltyServedEvent)
+ {
+ var isRightEvent = EventType == EventType.DriveThroughServed;
+ driveThroughPenaltyServedEvent = isRightEvent ? this.driveThroughPenaltyServedEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetFastestLapEvent(out FastestLapEvent fastestLapEvent)
+ {
+ var isRightEvent = EventType == EventType.FastestLap;
+ fastestLapEvent = isRightEvent ? this.fastestLapEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetFlashbackEvent(out FlashbackEvent flashbackEvent)
+ {
+ var isRightEvent = EventType == EventType.Flashback;
+ flashbackEvent = isRightEvent ? this.flashbackEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetOvertakeEvent(out OvertakeEvent overtakeEvent)
+ {
+ var isRightEvent = EventType == EventType.Overtake;
+ overtakeEvent = isRightEvent ? this.overtakeEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetPenaltyEvent(out PenaltyEvent penaltyEvent)
+ {
+ var isRightEvent = EventType == EventType.PenaltyIssued;
+ penaltyEvent = isRightEvent ? this.penaltyEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetRaceWinnerEvent(out RaceWinnerEvent raceWinnerEvent)
+ {
+ var isRightEvent = EventType == EventType.RaceWinner;
+ raceWinnerEvent = isRightEvent ? this.raceWinnerEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetRetirementEvent(out RetirementEvent retirementEvent)
+ {
+ var isRightEvent = EventType == EventType.Retirement;
+ retirementEvent = isRightEvent ? this.retirementEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetSpeedTrapEvent(out SpeedTrapEvent speedTrapEvent)
+ {
+ var isRightEvent = EventType == EventType.SpeedTrapTriggered;
+ speedTrapEvent = isRightEvent ? this.speedTrapEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetStartLightsEvent(out StartLightsEvent startLightsEvent)
+ {
+ var isRightEvent = EventType == EventType.StartLights;
+ startLightsEvent = isRightEvent ? this.startLightsEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetStopGoPenaltyServedEvent(out StopGoPenaltyServedEvent stopGoPenaltyServedEvent)
+ {
+ var isRightEvent = EventType == EventType.StopGoServed;
+ stopGoPenaltyServedEvent = isRightEvent ? this.stopGoPenaltyServedEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetTeamMateInPitsEvent(out TeamMateInPitsEvent teamMateInPitsEvent)
+ {
+ var isRightEvent = EventType == EventType.TeamMateInPits;
+ teamMateInPitsEvent = isRightEvent ? this.teamMateInPitsEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetCollisionEvent(out CollisionEvent collisionEvent)
+ {
+ var isRightEvent = EventType == EventType.Collision;
+ collisionEvent = isRightEvent ? this.collisionEvent : default;
+ return isRightEvent;
+ }
+
+ public bool TryGetSafetyCarEvent(out SafetyCarEvent safetyCarEvent)
+ {
+ var isRightEvent = EventType == EventType.SafetyCar;
+ safetyCarEvent = isRightEvent ? this.safetyCarEvent : default;
+ return isRightEvent;
+ }
+
+ void IByteWritable.WriteBytes(ref BytesWriter writer)
+ {
+ writer.WriteEnum(EventType);
+
+ IByteWritable? byteWritable = EventType switch
+ {
+ EventType.FastestLap => fastestLapEvent,
+ EventType.Retirement => retirementEvent,
+ EventType.TeamMateInPits => teamMateInPitsEvent,
+ EventType.RaceWinner => raceWinnerEvent,
+ EventType.PenaltyIssued => penaltyEvent,
+ EventType.SpeedTrapTriggered => speedTrapEvent,
+ EventType.StartLights => startLightsEvent,
+ EventType.DriveThroughServed => driveThroughPenaltyServedEvent,
+ EventType.StopGoServed => stopGoPenaltyServedEvent,
+ EventType.Flashback => flashbackEvent,
+ EventType.ButtonStatus => buttonsEvent,
+ EventType.Overtake => overtakeEvent,
+ EventType.SafetyCar => safetyCarEvent,
+ EventType.Collision => collisionEvent,
+ _ => null,
+ };
+
+ byteWritable?.WriteBytes(ref writer);
+ }
+
+ public static implicit operator EventDetails(ButtonsEvent buttonsEvent) => new(buttonsEvent);
+ public static implicit operator EventDetails(DriveThroughPenaltyServedEvent driveThroughPenaltyServedEvent) => new(driveThroughPenaltyServedEvent);
+ public static implicit operator EventDetails(FastestLapEvent fastestLapEvent) => new(fastestLapEvent);
+ public static implicit operator EventDetails(FlashbackEvent flashbackEvent) => new(flashbackEvent);
+ public static implicit operator EventDetails(OvertakeEvent overtakeEvent) => new(overtakeEvent);
+ public static implicit operator EventDetails(PenaltyEvent penaltyEvent) => new(penaltyEvent);
+ public static implicit operator EventDetails(RaceWinnerEvent raceWinnerEvent) => new(raceWinnerEvent);
+ public static implicit operator EventDetails(RetirementEvent retirementEvent) => new(retirementEvent);
+ public static implicit operator EventDetails(SpeedTrapEvent speedTrapEvent) => new(speedTrapEvent);
+ public static implicit operator EventDetails(StartLightsEvent startLightsEvent) => new(startLightsEvent);
+ public static implicit operator EventDetails(StopGoPenaltyServedEvent stopGoPenaltyServedEvent) => new(stopGoPenaltyServedEvent);
+ public static implicit operator EventDetails(TeamMateInPitsEvent teamMateInPitsEvent) => new(teamMateInPitsEvent);
+ public static implicit operator EventDetails(CollisionEvent collisionEvent) => new(collisionEvent);
+ public static implicit operator EventDetails(SafetyCarEvent safetyCarEvent) => new(safetyCarEvent);
}
diff --git a/F1Game.UDP/F1Game.UDP.csproj b/F1Game.UDP/F1Game.UDP.csproj
index e46b719..1ed4bae 100644
--- a/F1Game.UDP/F1Game.UDP.csproj
+++ b/F1Game.UDP/F1Game.UDP.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net8.0;net9.0
enable
enable
latest
diff --git a/F1Game.UDP/Packets/EventDataPacket.cs b/F1Game.UDP/Packets/EventDataPacket.cs
index 4a406d0..2bfbc4b 100644
--- a/F1Game.UDP/Packets/EventDataPacket.cs
+++ b/F1Game.UDP/Packets/EventDataPacket.cs
@@ -8,8 +8,8 @@ public readonly record struct EventDataPacket() : IByteParsable
{
public static int Size => 45;
- public PacketHeader Header { get; init; } = PacketHeader.Empty; // Header
- public EventDetails EventDetails { get; init; } // Event details - should be interpreted differently
+ public PacketHeader Header { get; init; } = PacketHeader.Empty;
+ public EventDetails EventDetails { get; init; }
static EventDataPacket IByteParsable.Parse(ref BytesReader reader)
{
@@ -50,27 +50,6 @@ static EventDataPacket IByteParsable.Parse(ref BytesReader read
void IByteWritable.WriteBytes(ref BytesWriter writer)
{
writer.Write(Header);
- writer.WriteEnum(EventDetails.EventType);
-
- IByteWritable? byteWritable = EventDetails.EventType switch
- {
- EventType.FastestLap => EventDetails.FastestLapEvent,
- EventType.Retirement => EventDetails.RetirementEvent,
- EventType.TeamMateInPits => EventDetails.TeamMateInPitsEvent,
- EventType.RaceWinner => EventDetails.RaceWinnerEvent,
- EventType.PenaltyIssued => EventDetails.PenaltyEvent,
- EventType.SpeedTrapTriggered => EventDetails.SpeedTrapEvent,
- EventType.StartLights => EventDetails.StartLightsEvent,
- EventType.DriveThroughServed => EventDetails.DriveThroughPenaltyServedEvent,
- EventType.StopGoServed => EventDetails.StopGoPenaltyServedEvent,
- EventType.Flashback => EventDetails.FlashbackEvent,
- EventType.ButtonStatus => EventDetails.ButtonsEvent,
- EventType.Overtake => EventDetails.OvertakeEvent,
- EventType.SafetyCar => EventDetails.SafetyCarEvent,
- EventType.Collision => EventDetails.CollisionEvent,
- _ => null,
- };
- if (byteWritable is not null)
- writer.Write(byteWritable);
+ writer.Write(EventDetails);
}
}
diff --git a/F1Game.UDP/Packets/UnionPacket.cs b/F1Game.UDP/Packets/UnionPacket.cs
index 2f181dd..82d015b 100644
--- a/F1Game.UDP/Packets/UnionPacket.cs
+++ b/F1Game.UDP/Packets/UnionPacket.cs
@@ -13,74 +13,195 @@ namespace F1Game.UDP.Packets;
[field: FieldOffset(0)]
public PacketHeader Header { get; init; }
[field: FieldOffset(0)]
- public CarDamageDataPacket CarDamageDataPacket { get; init; }
+ private readonly CarDamageDataPacket carDamageDataPacket;
[field: FieldOffset(0)]
- public CarSetupDataPacket CarSetupDataPacket { get; init; }
+ private readonly CarSetupDataPacket carSetupDataPacket;
[field: FieldOffset(0)]
- public CarStatusDataPacket CarStatusDataPacket { get; init; }
+ private readonly CarStatusDataPacket carStatusDataPacket;
[field: FieldOffset(0)]
- public CarTelemetryDataPacket CarTelemetryDataPacket { get; init; }
+ private readonly CarTelemetryDataPacket carTelemetryDataPacket;
[field: FieldOffset(0)]
- public EventDataPacket EventDataPacket { get; init; }
+ private readonly EventDataPacket eventDataPacket;
[field: FieldOffset(0)]
- public FinalClassificationDataPacket FinalClassificationDataPacket { get; init; }
+ private readonly FinalClassificationDataPacket finalClassificationDataPacket;
[field: FieldOffset(0)]
- public LapDataPacket LapDataPacket { get; init; }
+ private readonly LapDataPacket lapDataPacket;
[field: FieldOffset(0)]
- public LobbyInfoDataPacket LobbyInfoDataPacket { get; init; }
+ private readonly LobbyInfoDataPacket lobbyInfoDataPacket;
[field: FieldOffset(0)]
- public MotionDataPacket MotionDataPacket { get; init; }
+ private readonly MotionDataPacket motionDataPacket;
[field: FieldOffset(0)]
- public ParticipantsDataPacket ParticipantsDataPacket { get; init; }
+ private readonly ParticipantsDataPacket participantsDataPacket;
[field: FieldOffset(0)]
- public SessionDataPacket SessionDataPacket { get; init; }
+ private readonly SessionDataPacket sessionDataPacket;
[field: FieldOffset(0)]
- public SessionHistoryDataPacket SessionHistoryDataPacket { get; init; }
+ private readonly SessionHistoryDataPacket sessionHistoryDataPacket;
[field: FieldOffset(0)]
- public TyreSetsDataPacket TyreSetsDataPacket { get; init; }
+ private readonly TyreSetsDataPacket tyreSetsDataPacket;
[field: FieldOffset(0)]
- public MotionExDataPacket MotionExDataPacket { get; init; }
+ private readonly MotionExDataPacket motionExDataPacket;
[field: FieldOffset(0)]
- public TimeTrialDataPacket TimeTrialDataPacket { get; init; }
+ private readonly TimeTrialDataPacket timeTrialDataPacket;
+
+ public UnionPacket(CarDamageDataPacket carDamageDataPacket) => (this.carDamageDataPacket, PacketType) = (carDamageDataPacket, PacketType.CarDamage);
+ public UnionPacket(CarSetupDataPacket carSetupDataPacket) => (this.carSetupDataPacket, PacketType) = (carSetupDataPacket, PacketType.CarSetups);
+ public UnionPacket(CarStatusDataPacket carStatusDataPacket) => (this.carStatusDataPacket, PacketType) = (carStatusDataPacket, PacketType.CarStatus);
+ public UnionPacket(CarTelemetryDataPacket carTelemetryDataPacket) => (this.carTelemetryDataPacket, PacketType) = (carTelemetryDataPacket, PacketType.CarTelemetry);
+ public UnionPacket(EventDataPacket eventDataPacket) => (this.eventDataPacket, PacketType) = (eventDataPacket, PacketType.Event);
+ public UnionPacket(FinalClassificationDataPacket finalClassificationDataPacket) => (this.finalClassificationDataPacket, PacketType) = (finalClassificationDataPacket, PacketType.FinalClassification);
+ public UnionPacket(LapDataPacket lapDataPacket) => (this.lapDataPacket, PacketType) = (lapDataPacket, PacketType.LapData);
+ public UnionPacket(LobbyInfoDataPacket lobbyInfoDataPacket) => (this.lobbyInfoDataPacket, PacketType) = (lobbyInfoDataPacket, PacketType.LobbyInfo);
+ public UnionPacket(MotionDataPacket motionDataPacket) => (this.motionDataPacket, PacketType) = (motionDataPacket, PacketType.Motion);
+ public UnionPacket(ParticipantsDataPacket participantsDataPacket) => (this.participantsDataPacket, PacketType) = (participantsDataPacket, PacketType.Participants);
+ public UnionPacket(SessionDataPacket sessionDataPacket) => (this.sessionDataPacket, PacketType) = (sessionDataPacket, PacketType.Session);
+ public UnionPacket(SessionHistoryDataPacket sessionHistoryDataPacket) => (this.sessionHistoryDataPacket, PacketType) = (sessionHistoryDataPacket, PacketType.SessionHistory);
+ public UnionPacket(TyreSetsDataPacket tyreSetsDataPacket) => (this.tyreSetsDataPacket, PacketType) = (tyreSetsDataPacket, PacketType.TyreSets);
+ public UnionPacket(MotionExDataPacket motionExDataPacket) => (this.motionExDataPacket, PacketType) = (motionExDataPacket, PacketType.MotionEx);
+ public UnionPacket(TimeTrialDataPacket timeTrialDataPacket) => (this.timeTrialDataPacket, PacketType) = (timeTrialDataPacket, PacketType.TimeTrial);
+
+ public bool TryGetCarDamageDataPacket(out CarDamageDataPacket carDamageDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.CarDamage;
+ carDamageDataPacket = isRightPacket ? this.carDamageDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetCarSetupDataPacket(out CarSetupDataPacket carSetupDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.CarSetups;
+ carSetupDataPacket = isRightPacket ? this.carSetupDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetCarStatusDataPacket(out CarStatusDataPacket carStatusDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.CarStatus;
+ carStatusDataPacket = isRightPacket ? this.carStatusDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetCarTelemetryDataPacket(out CarTelemetryDataPacket carTelemetryDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.CarTelemetry;
+ carTelemetryDataPacket = isRightPacket ? this.carTelemetryDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetEventDataPacket(out EventDataPacket eventDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.Event;
+ eventDataPacket = isRightPacket ? this.eventDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetFinalClassificationDataPacket(out FinalClassificationDataPacket finalClassificationDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.FinalClassification;
+ finalClassificationDataPacket = isRightPacket ? this.finalClassificationDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetLapDataPacket(out LapDataPacket lapDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.LapData;
+ lapDataPacket = isRightPacket ? this.lapDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetLobbyInfoDataPacket(out LobbyInfoDataPacket lobbyInfoDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.LobbyInfo;
+ lobbyInfoDataPacket = isRightPacket ? this.lobbyInfoDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetMotionDataPacket(out MotionDataPacket motionDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.Motion;
+ motionDataPacket = isRightPacket ? this.motionDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetParticipantsDataPacket(out ParticipantsDataPacket participantsDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.Participants;
+ participantsDataPacket = isRightPacket ? this.participantsDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetSessionDataPacket(out SessionDataPacket sessionDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.Session;
+ sessionDataPacket = isRightPacket ? this.sessionDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetSessionHistoryDataPacket(out SessionHistoryDataPacket sessionHistoryDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.SessionHistory;
+ sessionHistoryDataPacket = isRightPacket ? this.sessionHistoryDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetTyreSetsDataPacket(out TyreSetsDataPacket tyreSetsDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.TyreSets;
+ tyreSetsDataPacket = isRightPacket ? this.tyreSetsDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetMotionExDataPacket(out MotionExDataPacket motionExDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.MotionEx;
+ motionExDataPacket = isRightPacket ? this.motionExDataPacket : default;
+ return isRightPacket;
+ }
+
+ public bool TryGetTimeTrialDataPacket(out TimeTrialDataPacket timeTrialDataPacket)
+ {
+ var isRightPacket = PacketType == PacketType.TimeTrial;
+ timeTrialDataPacket = isRightPacket ? this.timeTrialDataPacket : default;
+ return isRightPacket;
+ }
void IByteWritable.WriteBytes(ref BytesWriter writer)
{
IByteWritable byteWritable = PacketType switch
{
- PacketType.CarDamage => CarDamageDataPacket,
- PacketType.CarSetups => CarSetupDataPacket,
- PacketType.CarStatus => CarStatusDataPacket,
- PacketType.CarTelemetry => CarTelemetryDataPacket,
- PacketType.Event => EventDataPacket,
- PacketType.FinalClassification => FinalClassificationDataPacket,
- PacketType.MotionEx => MotionExDataPacket,
- PacketType.LapData => LapDataPacket,
- PacketType.LobbyInfo => LobbyInfoDataPacket,
- PacketType.Motion => MotionDataPacket,
- PacketType.Participants => ParticipantsDataPacket,
- PacketType.Session => SessionDataPacket,
- PacketType.SessionHistory => SessionHistoryDataPacket,
- PacketType.TyreSets => TyreSetsDataPacket,
- PacketType.TimeTrial => TimeTrialDataPacket,
+ PacketType.CarDamage => carDamageDataPacket,
+ PacketType.CarSetups => carSetupDataPacket,
+ PacketType.CarStatus => carStatusDataPacket,
+ PacketType.CarTelemetry => carTelemetryDataPacket,
+ PacketType.Event => eventDataPacket,
+ PacketType.FinalClassification => finalClassificationDataPacket,
+ PacketType.MotionEx => motionExDataPacket,
+ PacketType.LapData => lapDataPacket,
+ PacketType.LobbyInfo => lobbyInfoDataPacket,
+ PacketType.Motion => motionDataPacket,
+ PacketType.Participants => participantsDataPacket,
+ PacketType.Session => sessionDataPacket,
+ PacketType.SessionHistory => sessionHistoryDataPacket,
+ PacketType.TyreSets => tyreSetsDataPacket,
+ PacketType.TimeTrial => timeTrialDataPacket,
_ => throw new UnreachableException()
};
writer.Write(byteWritable);
}
- public static implicit operator UnionPacket(CarDamageDataPacket packet) => new() { CarDamageDataPacket = packet, PacketType = PacketType.CarDamage };
- public static implicit operator UnionPacket(CarSetupDataPacket packet) => new() { CarSetupDataPacket = packet, PacketType = PacketType.CarSetups };
- public static implicit operator UnionPacket(CarStatusDataPacket packet) => new() { CarStatusDataPacket = packet, PacketType = PacketType.CarStatus };
- public static implicit operator UnionPacket(CarTelemetryDataPacket packet) => new() { CarTelemetryDataPacket = packet, PacketType = PacketType.CarTelemetry };
- public static implicit operator UnionPacket(EventDataPacket packet) => new() { EventDataPacket = packet, PacketType = PacketType.Event };
- public static implicit operator UnionPacket(FinalClassificationDataPacket packet) => new() { FinalClassificationDataPacket = packet, PacketType = PacketType.FinalClassification };
- public static implicit operator UnionPacket(LapDataPacket packet) => new() { LapDataPacket = packet, PacketType = PacketType.LapData };
- public static implicit operator UnionPacket(LobbyInfoDataPacket packet) => new() { LobbyInfoDataPacket = packet, PacketType = PacketType.LobbyInfo };
- public static implicit operator UnionPacket(MotionDataPacket packet) => new() { MotionDataPacket = packet, PacketType = PacketType.Motion };
- public static implicit operator UnionPacket(ParticipantsDataPacket packet) => new() { ParticipantsDataPacket = packet, PacketType = PacketType.Participants };
- public static implicit operator UnionPacket(SessionDataPacket packet) => new() { SessionDataPacket = packet, PacketType = PacketType.Session };
- public static implicit operator UnionPacket(SessionHistoryDataPacket packet) => new() { SessionHistoryDataPacket = packet, PacketType = PacketType.SessionHistory };
- public static implicit operator UnionPacket(TyreSetsDataPacket packet) => new() { TyreSetsDataPacket = packet, PacketType = PacketType.TyreSets };
- public static implicit operator UnionPacket(MotionExDataPacket packet) => new() { MotionExDataPacket = packet, PacketType = PacketType.MotionEx };
- public static implicit operator UnionPacket(TimeTrialDataPacket packet) => new() { TimeTrialDataPacket = packet, PacketType = PacketType.TimeTrial };
+ public static implicit operator UnionPacket(CarDamageDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(CarSetupDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(CarStatusDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(CarTelemetryDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(EventDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(FinalClassificationDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(LapDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(LobbyInfoDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(MotionDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(ParticipantsDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(SessionDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(SessionHistoryDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(TyreSetsDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(MotionExDataPacket packet) => new(packet);
+ public static implicit operator UnionPacket(TimeTrialDataPacket packet) => new(packet);
}
diff --git a/README.md b/README.md
index f6942c3..6b737ca 100644
--- a/README.md
+++ b/README.md
@@ -33,31 +33,35 @@ The `ToPacket` method returns a `UnionPacket` struct, which has properties for d
- `TimeTrialDataPacket`
- `TyreSetsDataPacket`
-You can access the specific packet data by accessing the corresponding property of the `UnionPacket` struct, you should check what packet type it is first using `PacketType` property.
+First, check the packet type using the `PacketType` property. Then, access the specific packet data by calling the corresponding `TryGet` method of the `UnionPacket` struct.
```
using F1Game.UDP;
UnionPacket packet = arrayOfBytes.ToPacket();
-if (packet.PacketType == PacketType.CarTelemetry)
+if (packet.TryGetCarTelemetryDataPacket(out var carTelemetryData))
{
- CarTelemetryDataPacket carTelemetryData = packet.CarTelemetryData;
// Access car telemetry data
}
switch (packet.PacketType)
{
- case PacketType.CarTelemetry:
- CarTelemetryDataPacket carTelemetryData = packet.CarTelemetryData;
+ case PacketType.CarTelemetry when packet.TryGetCarTelemetryDataPacket(out var carTelemetryData):
// Access car telemetry data
break;
- case PacketType.CarStatus:
- CarStatusDataPacket carStatusData = packet.CarStatusData;
+ case PacketType.CarStatus when packet.TryGetCarStatusDataPacket(out var carStatusData):
// Access car status data
break;
// Add other cases for different packet types
}
+
+var someResult = packet.PacketType switch
+{
+ PacketType.CarTelemetry when packet.TryGetCarTelemetryDataPacket(out var carTelemetryData) => // Access car telemetry data,
+ PacketType.CarStatus when packet.TryGetCarStatusDataPacket(out var carStatusData) => // Access car status data,
+ _ => "default"
+};
```
# Benchmarks