From 6e915ea1e0c7d648a81e162aa1fa44022e50cbf0 Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Wed, 16 Sep 2026 21:36:33 +0100 Subject: [PATCH 1/2] return the outgauge for access --- bngsdk.go | 224 ++----------------------------------------------- outgauge.go | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 241 insertions(+), 218 deletions(-) diff --git a/bngsdk.go b/bngsdk.go index eacfd07..f1d9784 100644 --- a/bngsdk.go +++ b/bngsdk.go @@ -2,11 +2,8 @@ package bngsdk import ( - "encoding/binary" "io" "log/slog" - "math" - "unsafe" ) const ( @@ -50,12 +47,9 @@ type BeamNGSDK struct { func NewBngSDK(opts Options) (*BeamNGSDK, error) { sdk := BeamNGSDK{ Opts: opts, - buffer: make([]byte, unsafe.Sizeof(Outgauge{})), + buffer: make([]byte, outgaugeSize), } - // Set the passed logger as the default logger - slog.SetDefault(sdk.Opts.Logger) - var err error err = sdk.openReader() @@ -162,236 +156,34 @@ func (sdk *BeamNGSDK) openWriter() error { return nil } -func (sdk *BeamNGSDK) Update() (int, error) { - var nBytes int +func (sdk *BeamNGSDK) Update() (*Outgauge, error) { var err error - nBytes, err = sdk.reader.Next(sdk.buffer) + _, err = sdk.reader.Next(sdk.buffer) // We check this first because we want to know if we need to loop if err == io.EOF { if sdk.Opts.Loop { err = sdk.reader.Reset() if err != nil { - return 0, err + return nil, err } } // NOTE: could we make the reset return the next piece of data? // We update to the start of the file since we had to reset - nBytes, err = sdk.reader.Next(sdk.buffer) + _, err = sdk.reader.Next(sdk.buffer) } if err != nil { - return 0, err + return nil, err } if sdk.Opts.ExportData { sdk.writer.Write(sdk.buffer) } - return nBytes, sdk.parseData(sdk.buffer) -} - -func ParseData(ogData *Outgauge, buffer []byte) error { - ogData.Time = binary.LittleEndian.Uint32(buffer[0:4]) - copy(ogData.Car[:], buffer[4:8]) - ogData.Flags = binary.LittleEndian.Uint16(buffer[8:10]) - ogData.Gear = int8(buffer[10]) - ogData.Plid = int8(buffer[11]) - ogData.Speed = math.Float32frombits(binary.LittleEndian.Uint32(buffer[12:16])) - ogData.RPM = math.Float32frombits(binary.LittleEndian.Uint32(buffer[16:20])) - ogData.Turbo = math.Float32frombits(binary.LittleEndian.Uint32(buffer[20:24])) - ogData.EngTemp = math.Float32frombits(binary.LittleEndian.Uint32(buffer[24:28])) - ogData.Fuel = math.Float32frombits(binary.LittleEndian.Uint32(buffer[28:32])) - ogData.OilPressure = math.Float32frombits(binary.LittleEndian.Uint32(buffer[32:36])) - ogData.OilTemp = math.Float32frombits(binary.LittleEndian.Uint32(buffer[36:40])) - ogData.DashLights = binary.LittleEndian.Uint32(buffer[40:44]) - ogData.ShowLights = binary.LittleEndian.Uint32(buffer[44:48]) - ogData.Throttle = math.Float32frombits(binary.LittleEndian.Uint32(buffer[48:52])) - ogData.Brake = math.Float32frombits(binary.LittleEndian.Uint32(buffer[52:56])) - ogData.Clutch = math.Float32frombits(binary.LittleEndian.Uint32(buffer[56:60])) - copy(ogData.Display1[:], buffer[60:76]) - copy(ogData.Display2[:], buffer[76:92]) - ogData.ID = int32(binary.LittleEndian.Uint32(buffer[92:96])) - - return nil + return &sdk.Data, sdk.parseData(sdk.buffer) } func (sdk *BeamNGSDK) parseData(buffer []byte) error { - return ParseData(&sdk.Data, buffer) + return sdk.Data.ParseData(buffer) } - -// SDK utilities - -// ShowLights - functions to check if a given dash light is on [START] - -// ShiftLight reports whether the shift light is on -func (sdk *BeamNGSDK) ShiftLight() bool { - return sdk.Data.ShowLights&DL_SHIFT != 0 -} - -// HighBeam reports whether high beams are on -func (sdk *BeamNGSDK) HighBeam() bool { - return sdk.Data.ShowLights&DL_FULLBEAM != 0 -} - -// Handbrake reports whether the handbrake is pulled -func (sdk *BeamNGSDK) Handbrake() bool { - return sdk.Data.ShowLights&DL_HANDBRAKE != 0 -} - -// Pitspeed reports whether the pit speed limiter is engaged -// -// NOTE: this may not be used in BeamNG.drive, haven't checked yet -func (sdk *BeamNGSDK) Pitspeed() bool { - return sdk.Data.ShowLights&DL_PITSPEED != 0 -} - -// TractionControl reports wheter TC is engaged -func (sdk *BeamNGSDK) TractionControl() bool { - return sdk.Data.ShowLights&DL_TC != 0 -} - -// LeftIndicator reports whether the left indicator is on -func (sdk *BeamNGSDK) LeftIndicator() bool { - return sdk.Data.ShowLights&DL_SIGNAL_L != 0 -} - -// RightIndicator reports wheter the right indicator is on -func (sdk *BeamNGSDK) RightIndicator() bool { - return sdk.Data.ShowLights&DL_SIGNAL_R != 0 -} - -// AnyIndicator reports whether any indicator is on -func (sdk *BeamNGSDK) AnyIndicator() bool { - return sdk.Data.ShowLights&DL_SIGNAL_ANY != 0 -} - -// OilLight reports whether the oil warning light is on -func (sdk *BeamNGSDK) OilLight() bool { - return sdk.Data.ShowLights&DL_OILWARN != 0 -} - -// BatteryLight reports whether the battery light is on -func (sdk *BeamNGSDK) BatteryLight() bool { - return sdk.Data.ShowLights&DL_BATTERY != 0 -} - -// ABS reports whether the ABS light is on -func (sdk *BeamNGSDK) ABS() bool { - return sdk.Data.ShowLights&DL_ABS != 0 -} - -// ShowLights - functions to check if a given dash light is on [END] - -// DashLights - functions to check if a given dash light is provided [START] - -// HasShiftLight reports whether a shift light is available -func (sdk *BeamNGSDK) HasShiftLight() bool { - return sdk.Data.DashLights&DL_SHIFT != 0 -} - -// HasHighBeamLight reports whether a high beam light is available -func (sdk *BeamNGSDK) HasHighBeamLight() bool { - return sdk.Data.DashLights&DL_FULLBEAM != 0 -} - -// HasHandbrakeLight reports wheter a handbrake light is available -func (sdk *BeamNGSDK) HasHandbrakeLight() bool { - return sdk.Data.DashLights&DL_HANDBRAKE != 0 -} - -// HasPitspeed reports whether a pit speed limitr is available -// NOTE: this may not be used in BeamNG.drive, haven't checked yet -func (sdk *BeamNGSDK) HasPitspeed() bool { - return sdk.Data.DashLights&DL_PITSPEED != 0 -} - -// HasTractionControlLight reports whether a traction control light is available -func (sdk *BeamNGSDK) HasTractionControlLight() bool { - return sdk.Data.DashLights&DL_TC != 0 -} - -// HasLeftIndicatorLight reports whether a left indicator is available -func (sdk *BeamNGSDK) HasLeftIndicatorLight() bool { - return sdk.Data.DashLights&DL_SIGNAL_L != 0 -} - -// HasRightIndicatorLight reports whether a right indicator is available -func (sdk *BeamNGSDK) HasRightIndicatorLight() bool { - return sdk.Data.DashLights&DL_SIGNAL_R != 0 -} - -// HasAnyIndicatorLight reports whether an any indicator light is available -func (sdk *BeamNGSDK) HasAnyIndicatorLight() bool { - return sdk.Data.DashLights&DL_SIGNAL_ANY != 0 -} - -// HasOilLight reports whether a oil light is available -func (sdk *BeamNGSDK) HasOilLight() bool { - return sdk.Data.DashLights&DL_OILWARN != 0 -} - -// HasBatteryLight reports whether a battery light is available -func (sdk *BeamNGSDK) HasBatteryLight() bool { - return sdk.Data.DashLights&DL_BATTERY != 0 -} - -// HasABSLight reports whether an ABS light is available -func (sdk *BeamNGSDK) HasABSLight() bool { - return sdk.Data.DashLights&DL_ABS != 0 -} - -// DashLights - functions to check if a given dash light is provided [END] - -// Flags - functions to check if a given flag is ON [START] - -// HasTurbo reports whether there's a turbo -func (sdk *BeamNGSDK) HasTurbo() bool { - return sdk.Data.Flags&OG_TURBO != 0 -} - -// PrefersKm reports whether the user prefers kilometers: -// - true is prefers Km -// - false is prefers Mi -func (sdk *BeamNGSDK) PrefersKm() bool { - return sdk.Data.Flags&OG_KM != 0 -} - -// PrefersBAR reports whether the user prefers BAR: -// - true is prefers BAR -// - false is prefers PSI -func (sdk *BeamNGSDK) PrefersBAR() bool { - return sdk.Data.Flags&OG_BAR != 0 -} - -// Flags - functions to check if a given flag is ON [END] - -// Data Retrieval [START] - -// ToMap creates a map with the data in the Outgauge struct -func (sdk *BeamNGSDK) ToMap() map[string]any { - return map[string]any{ - "Time": sdk.Data.Time, // time in milliseconds (to check order) - "Car": sdk.Data.Car, // Car name - "Flags": sdk.Data.Flags, // Info (see OG_x below) - "Gear": sdk.Data.Gear, // Reverse:0, Neutral:1, First:2... - "Plid": sdk.Data.Plid, // Unique ID of viewed player (0 = none) - "Speed": sdk.Data.Speed, // M/S - "RPM": sdk.Data.RPM, // RPM - "Turbo": sdk.Data.Turbo, // BAR - "EngTemp": sdk.Data.EngTemp, // C - "Fuel": sdk.Data.Fuel, // 0 to 1 - "OilPressure": sdk.Data.OilPressure, // BAR - "OilTemp": sdk.Data.OilTemp, // C - "DashLights": sdk.Data.DashLights, // Dash lights available (see DL_x below) - "ShowLights": sdk.Data.ShowLights, // Dash lights currently switched on - "Throttle": sdk.Data.Throttle, // 0 to 1 - "Brake": sdk.Data.Brake, // 0 to 1 - "Clutch": sdk.Data.Clutch, // 0 to 1 - "Display1": sdk.Data.Display1, // Usually Fuel - "Display2": sdk.Data.Display2, // Usually Settings - "ID": sdk.Data.ID, // optional - only if OutGauge ID is specified - } -} - -// Data Retrieval [END] diff --git a/outgauge.go b/outgauge.go index e2dcbab..e5fe08e 100644 --- a/outgauge.go +++ b/outgauge.go @@ -1,8 +1,15 @@ package bngsdk -import "encoding/binary" +import ( + "encoding/binary" + "errors" + "math" +) -var outgaugeSize = binary.Size(Outgauge{}) +var ( + outgaugeSize = binary.Size(Outgauge{}) + ErrNotEnoughData = errors.New("buffer len is too short for Outgauge unpacking") +) // More documentation at https://go.beamng.com/protocols. // Or at BeamNG/lua/vehicle/protocols/outgauge.lua @@ -33,6 +40,7 @@ const ( // Outgauge describes the data served by the BeamNG outgauge server type Outgauge struct { + // data []byte Time uint32 // time in milliseconds (to check order) Car [4]byte // Car name Flags uint16 // Info (see OG_x below) @@ -54,3 +62,226 @@ type Outgauge struct { Display2 [16]byte // Usually Settings ID int32 // optional - only if OutGauge ID is specified } + +func (og *Outgauge) ParseData(buffer []byte) error { + if len(buffer) < outgaugeSize { + return ErrNotEnoughData + } + + og.Time = binary.LittleEndian.Uint32(buffer[0:4]) + copy(og.Car[:], buffer[4:8]) + og.Flags = binary.LittleEndian.Uint16(buffer[8:10]) + og.Gear = int8(buffer[10]) + og.Plid = int8(buffer[11]) + og.Speed = math.Float32frombits(binary.LittleEndian.Uint32(buffer[12:16])) + og.RPM = math.Float32frombits(binary.LittleEndian.Uint32(buffer[16:20])) + og.Turbo = math.Float32frombits(binary.LittleEndian.Uint32(buffer[20:24])) + og.EngTemp = math.Float32frombits(binary.LittleEndian.Uint32(buffer[24:28])) + og.Fuel = math.Float32frombits(binary.LittleEndian.Uint32(buffer[28:32])) + og.OilPressure = math.Float32frombits(binary.LittleEndian.Uint32(buffer[32:36])) + og.OilTemp = math.Float32frombits(binary.LittleEndian.Uint32(buffer[36:40])) + og.DashLights = binary.LittleEndian.Uint32(buffer[40:44]) + og.ShowLights = binary.LittleEndian.Uint32(buffer[44:48]) + og.Throttle = math.Float32frombits(binary.LittleEndian.Uint32(buffer[48:52])) + og.Brake = math.Float32frombits(binary.LittleEndian.Uint32(buffer[52:56])) + og.Clutch = math.Float32frombits(binary.LittleEndian.Uint32(buffer[56:60])) + copy(og.Display1[:], buffer[60:76]) + copy(og.Display2[:], buffer[76:92]) + og.ID = int32(binary.LittleEndian.Uint32(buffer[92:96])) + + return nil +} + +// TODO: think about having direct memory access for the fields instead of +// parsing everything +// func NewOutgauge(buffer []byte) (*Outgauge, error) { +// if len(buffer) < outgaugeSize { +// return nil, ErrNotEnoughData +// } +// +// og := &Outgauge{ +// data: make([]byte, outgaugeSize), +// } +// +// return og, nil +// } + +// SDK utilities + +// Values Getters [START] + +// Values Getters [END] + +// ShowLights - functions to check if a given dash light is on [START] + +// ShiftLight reports whether the shift light is on +func (og *Outgauge) ShiftLight() bool { + return og.ShowLights&DL_SHIFT != 0 +} + +// HighBeam reports whether high beams are on +func (og *Outgauge) HighBeam() bool { + return og.ShowLights&DL_FULLBEAM != 0 +} + +// Handbrake reports whether the handbrake is pulled +func (og *Outgauge) Handbrake() bool { + return og.ShowLights&DL_HANDBRAKE != 0 +} + +// Pitspeed reports whether the pit speed limiter is engaged +// +// NOTE: this may not be used in BeamNG.drive, haven't checked yet +func (og *Outgauge) Pitspeed() bool { + return og.ShowLights&DL_PITSPEED != 0 +} + +// TractionControl reports wheter TC is engaged +func (og *Outgauge) TractionControl() bool { + return og.ShowLights&DL_TC != 0 +} + +// LeftIndicator reports whether the left indicator is on +func (og *Outgauge) LeftIndicator() bool { + return og.ShowLights&DL_SIGNAL_L != 0 +} + +// RightIndicator reports wheter the right indicator is on +func (og *Outgauge) RightIndicator() bool { + return og.ShowLights&DL_SIGNAL_R != 0 +} + +// AnyIndicator reports whether any indicator is on +func (og *Outgauge) AnyIndicator() bool { + return og.ShowLights&DL_SIGNAL_ANY != 0 +} + +// OilLight reports whether the oil warning light is on +func (og *Outgauge) OilLight() bool { + return og.ShowLights&DL_OILWARN != 0 +} + +// BatteryLight reports whether the battery light is on +func (og *Outgauge) BatteryLight() bool { + return og.ShowLights&DL_BATTERY != 0 +} + +// ABS reports whether the ABS light is on +func (og *Outgauge) ABS() bool { + return og.ShowLights&DL_ABS != 0 +} + +// ShowLights - functions to check if a given dash light is on [END] + +// DashLights - functions to check if a given dash light is provided [START] + +// HasShiftLight reports whether a shift light is available +func (og *Outgauge) HasShiftLight() bool { + return og.DashLights&DL_SHIFT != 0 +} + +// HasHighBeamLight reports whether a high beam light is available +func (og *Outgauge) HasHighBeamLight() bool { + return og.DashLights&DL_FULLBEAM != 0 +} + +// HasHandbrakeLight reports wheter a handbrake light is available +func (og *Outgauge) HasHandbrakeLight() bool { + return og.DashLights&DL_HANDBRAKE != 0 +} + +// HasPitspeed reports whether a pit speed limitr is available +// NOTE: this may not be used in BeamNG.drive, haven't checked yet +func (og *Outgauge) HasPitspeed() bool { + return og.DashLights&DL_PITSPEED != 0 +} + +// HasTractionControlLight reports whether a traction control light is available +func (og *Outgauge) HasTractionControlLight() bool { + return og.DashLights&DL_TC != 0 +} + +// HasLeftIndicatorLight reports whether a left indicator is available +func (og *Outgauge) HasLeftIndicatorLight() bool { + return og.DashLights&DL_SIGNAL_L != 0 +} + +// HasRightIndicatorLight reports whether a right indicator is available +func (og *Outgauge) HasRightIndicatorLight() bool { + return og.DashLights&DL_SIGNAL_R != 0 +} + +// HasAnyIndicatorLight reports whether an any indicator light is available +func (og *Outgauge) HasAnyIndicatorLight() bool { + return og.DashLights&DL_SIGNAL_ANY != 0 +} + +// HasOilLight reports whether a oil light is available +func (og *Outgauge) HasOilLight() bool { + return og.DashLights&DL_OILWARN != 0 +} + +// HasBatteryLight reports whether a battery light is available +func (og *Outgauge) HasBatteryLight() bool { + return og.DashLights&DL_BATTERY != 0 +} + +// HasABSLight reports whether an ABS light is available +func (og *Outgauge) HasABSLight() bool { + return og.DashLights&DL_ABS != 0 +} + +// DashLights - functions to check if a given dash light is provided [END] + +// Flags - functions to check if a given flag is ON [START] + +// HasTurbo reports whether there's a turbo +func (og *Outgauge) HasTurbo() bool { + return og.Flags&OG_TURBO != 0 +} + +// PrefersKm reports whether the user prefers kilometers: +// - true is prefers Km +// - false is prefers Mi +func (og *Outgauge) PrefersKm() bool { + return og.Flags&OG_KM != 0 +} + +// PrefersBAR reports whether the user prefers BAR: +// - true is prefers BAR +// - false is prefers PSI +func (og *Outgauge) PrefersBAR() bool { + return og.Flags&OG_BAR != 0 +} + +// Flags - functions to check if a given flag is ON [END] + +// Data Retrieval [START] + +// ToMap creates a map with the data in the Outgauge struct +func (sdk *BeamNGSDK) ToMap() map[string]any { + return map[string]any{ + "Time": sdk.Data.Time, // time in milliseconds (to check order) + "Car": sdk.Data.Car, // Car name + "Flags": sdk.Data.Flags, // Info (see OG_x below) + "Gear": sdk.Data.Gear, // Reverse:0, Neutral:1, First:2... + "Plid": sdk.Data.Plid, // Unique ID of viewed player (0 = none) + "Speed": sdk.Data.Speed, // M/S + "RPM": sdk.Data.RPM, // RPM + "Turbo": sdk.Data.Turbo, // BAR + "EngTemp": sdk.Data.EngTemp, // C + "Fuel": sdk.Data.Fuel, // 0 to 1 + "OilPressure": sdk.Data.OilPressure, // BAR + "OilTemp": sdk.Data.OilTemp, // C + "DashLights": sdk.Data.DashLights, // Dash lights available (see DL_x below) + "ShowLights": sdk.Data.ShowLights, // Dash lights currently switched on + "Throttle": sdk.Data.Throttle, // 0 to 1 + "Brake": sdk.Data.Brake, // 0 to 1 + "Clutch": sdk.Data.Clutch, // 0 to 1 + "Display1": sdk.Data.Display1, // Usually Fuel + "Display2": sdk.Data.Display2, // Usually Settings + "ID": sdk.Data.ID, // optional - only if OutGauge ID is specified + } +} + +// Data Retrieval [END] -- 2.54.0 From d9b7c185ed649ddb707b16ca01f8084285daeb78 Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Wed, 16 Sep 2026 21:38:59 +0100 Subject: [PATCH 2/2] update the examples --- bngsdk.go | 6 ++--- example/read_binary_file/main.go | 4 ++-- example/read_socket_data/main.go | 4 ++-- outgauge.go | 40 ++++++++++++++++---------------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/bngsdk.go b/bngsdk.go index f1d9784..2c6aed2 100644 --- a/bngsdk.go +++ b/bngsdk.go @@ -40,7 +40,7 @@ type BeamNGSDK struct { Opts Options reader BngImporter writer BngExporter - Data Outgauge + data Outgauge buffer []byte } @@ -181,9 +181,9 @@ func (sdk *BeamNGSDK) Update() (*Outgauge, error) { sdk.writer.Write(sdk.buffer) } - return &sdk.Data, sdk.parseData(sdk.buffer) + return &sdk.data, sdk.parseData(sdk.buffer) } func (sdk *BeamNGSDK) parseData(buffer []byte) error { - return sdk.Data.ParseData(buffer) + return sdk.data.ParseData(buffer) } diff --git a/example/read_binary_file/main.go b/example/read_binary_file/main.go index 5008ef3..83b18c9 100644 --- a/example/read_binary_file/main.go +++ b/example/read_binary_file/main.go @@ -45,7 +45,7 @@ func main() { for { select { case <-ticker.C: - _, err := sdk.Update() + og, err := sdk.Update() if err != nil { log.Fatalf("failed to update data: %+v", err) } @@ -53,7 +53,7 @@ func main() { fmt.Printf("\033[?25l\033[2J\033[H") fmt.Printf( "Gear: %d, RPM: %f, Speed: %f\n", - sdk.Data.Gear, sdk.Data.RPM, sdk.Data.Speed, + og.Gear, og.RPM, og.Speed, ) } } diff --git a/example/read_socket_data/main.go b/example/read_socket_data/main.go index 1b99a24..3fb2ec1 100644 --- a/example/read_socket_data/main.go +++ b/example/read_socket_data/main.go @@ -41,7 +41,7 @@ func main() { for { select { case <-ticker.C: - _, err := sdk.Update() + og, err := sdk.Update() if err != nil { log.Fatalf("failed to update data: %+v", err) } @@ -49,7 +49,7 @@ func main() { fmt.Printf("\033[?25l\033[2J\033[H") fmt.Printf( "Gear: %d, RPM: %f, Speed: %f\n", - sdk.Data.Gear, sdk.Data.RPM, sdk.Data.Speed, + og.Gear, og.RPM, og.Speed, ) } } diff --git a/outgauge.go b/outgauge.go index e5fe08e..24c737a 100644 --- a/outgauge.go +++ b/outgauge.go @@ -261,26 +261,26 @@ func (og *Outgauge) PrefersBAR() bool { // ToMap creates a map with the data in the Outgauge struct func (sdk *BeamNGSDK) ToMap() map[string]any { return map[string]any{ - "Time": sdk.Data.Time, // time in milliseconds (to check order) - "Car": sdk.Data.Car, // Car name - "Flags": sdk.Data.Flags, // Info (see OG_x below) - "Gear": sdk.Data.Gear, // Reverse:0, Neutral:1, First:2... - "Plid": sdk.Data.Plid, // Unique ID of viewed player (0 = none) - "Speed": sdk.Data.Speed, // M/S - "RPM": sdk.Data.RPM, // RPM - "Turbo": sdk.Data.Turbo, // BAR - "EngTemp": sdk.Data.EngTemp, // C - "Fuel": sdk.Data.Fuel, // 0 to 1 - "OilPressure": sdk.Data.OilPressure, // BAR - "OilTemp": sdk.Data.OilTemp, // C - "DashLights": sdk.Data.DashLights, // Dash lights available (see DL_x below) - "ShowLights": sdk.Data.ShowLights, // Dash lights currently switched on - "Throttle": sdk.Data.Throttle, // 0 to 1 - "Brake": sdk.Data.Brake, // 0 to 1 - "Clutch": sdk.Data.Clutch, // 0 to 1 - "Display1": sdk.Data.Display1, // Usually Fuel - "Display2": sdk.Data.Display2, // Usually Settings - "ID": sdk.Data.ID, // optional - only if OutGauge ID is specified + "Time": sdk.data.Time, // time in milliseconds (to check order) + "Car": sdk.data.Car, // Car name + "Flags": sdk.data.Flags, // Info (see OG_x below) + "Gear": sdk.data.Gear, // Reverse:0, Neutral:1, First:2... + "Plid": sdk.data.Plid, // Unique ID of viewed player (0 = none) + "Speed": sdk.data.Speed, // M/S + "RPM": sdk.data.RPM, // RPM + "Turbo": sdk.data.Turbo, // BAR + "EngTemp": sdk.data.EngTemp, // C + "Fuel": sdk.data.Fuel, // 0 to 1 + "OilPressure": sdk.data.OilPressure, // BAR + "OilTemp": sdk.data.OilTemp, // C + "DashLights": sdk.data.DashLights, // Dash lights available (see DL_x below) + "ShowLights": sdk.data.ShowLights, // Dash lights currently switched on + "Throttle": sdk.data.Throttle, // 0 to 1 + "Brake": sdk.data.Brake, // 0 to 1 + "Clutch": sdk.data.Clutch, // 0 to 1 + "Display1": sdk.data.Display1, // Usually Fuel + "Display2": sdk.data.Display2, // Usually Settings + "ID": sdk.data.ID, // optional - only if OutGauge ID is specified } } -- 2.54.0