Compare commits

..

No commits in common. "dc729b3f10b96e9789cf8449aa5e9ad1e542716e" and "df031f3c19203bd3fecfc91381cec0a03aee264f" have entirely different histories.

3 changed files with 25 additions and 963 deletions

View file

@ -1,868 +0,0 @@
/*
rF2 internal state mapping structures. Allows access to native C++ structs from C#.
Must be kept in sync with Include\rF2State.h.
See: MainForm.MainUpdate for sample on how to marshall from native in memory struct.
Author: The Iron Wolf (vleonavicius@hotmail.com)
Website: thecrewchief.org
*/
using System;
using System.Runtime.InteropServices;
using System.Xml.Serialization;
// CC specific: Mark more common unused members with XmlIgnore for reduced trace sizes.
namespace CrewChiefV4.rFactor2
{
// Marshalled types:
// C++ C#
// char -> byte
// unsigned char -> byte
// signed char -> sbyte
// bool -> byte
// long -> int
// ULONGLONG -> Int64
// unsigned long -> uint
public class rFactor2Constants
{
public const string MM_TELEMETRY_FILE_NAME = "$rFactor2SMMP_Telemetry$";
public const string MM_SCORING_FILE_NAME = "$rFactor2SMMP_Scoring$";
public const string MM_RULES_FILE_NAME = "$rFactor2SMMP_Rules$";
public const string MM_EXTENDED_FILE_NAME = "$rFactor2SMMP_Extended$";
public const int MAX_MAPPED_VEHICLES = 128;
public const int MAX_MAPPED_IDS = 512;
public const string RFACTOR2_PROCESS_NAME = "rFactor2";
public const byte RowX = 0;
public const byte RowY = 1;
public const byte RowZ = 2;
// 0 Before session has begun
// 1 Reconnaissance laps (race only)
// 2 Grid walk-through (race only)
// 3 Formation lap (race only)
// 4 Starting-light countdown has begun (race only)
// 5 Green flag
// 6 Full course yellow / safety car
// 7 Session stopped
// 8 Session over
public enum rF2GamePhase
{
Garage = 0,
WarmUp = 1,
GridWalk = 2,
Formation = 3,
Countdown = 4,
GreenFlag = 5,
FullCourseYellow = 6,
SessionStopped = 7,
SessionOver = 8,
Undocumented_PreRace = 9 // I suspect 9 means we're in a garage/monitor, waiting for race to start.
}
// Yellow flag states (applies to full-course only)
// -1 Invalid
// 0 None
// 1 Pending
// 2 Pits closed
// 3 Pit lead lap
// 4 Pits open
// 5 Last lap
// 6 Resume
// 7 Race halt (not currently used)
public enum rF2YellowFlagState
{
Invalid = -1,
NoFlag = 0,
Pending = 1,
PitClosed = 2,
PitLeadLap = 3,
PitOpen = 4,
LastLap = 5,
Resume = 6,
RaceHalt = 7
}
// 0=dry, 1=wet, 2=grass, 3=dirt, 4=gravel, 5=rumblestrip, 6=special
public enum rF2SurfaceType
{
Dry = 0,
Wet = 1,
Grass = 2,
Dirt = 3,
Gravel = 4,
Kerb = 5,
Special = 6
}
// 0=sector3, 1=sector1, 2=sector2 (don't ask why)
public enum rF2Sector
{
Sector3 = 0,
Sector1 = 1,
Sector2 = 2
}
// 0=none, 1=finished, 2=dnf, 3=dq
public enum rF2FinishStatus
{
None = 0,
Finished = 1,
Dnf = 2,
Dq = 3
}
// who's in control: -1=nobody (shouldn't get this), 0=local player, 1=local AI, 2=remote, 3=replay (shouldn't get this)
public enum rF2Control
{
Nobody = -1,
Player = 0,
AI = 1,
Remote = 2,
Replay = 3
}
// wheel info (front left, front right, rear left, rear right)
public enum rF2WheelIndex
{
FrontLeft = 0,
FrontRight = 1,
RearLeft = 2,
RearRight = 3
}
// 0=none, 1=request, 2=entering, 3=stopped, 4=exiting
public enum rF2PitState
{
None = 0,
Request = 1,
Entering = 2,
Stopped = 3,
Exiting = 4
}
// primary flag being shown to vehicle (currently only 0=green or 6=blue)
public enum rF2PrimaryFlag
{
Green = 0,
Blue = 6
}
// 0 = do not count lap or time, 1 = count lap but not time, 2 = count lap and time
public enum rF2CountLapFlag
{
DoNotCountLap = 0,
CountLapButNotTime = 1,
CountLapAndTime = 2,
}
// 0=disallowed, 1=criteria detected but not allowed quite yet, 2=allowed
public enum rF2RearFlapLegalStatus
{
Disallowed = 0,
DetectedButNotAllowedYet = 1,
Alllowed = 2
}
// 0=off 1=ignition 2=ignition+starter
public enum rF2IgnitionStarterStatus
{
Off = 0,
Ignition = 1,
IgnitionAndStarter = 2
}
}
namespace rFactor2Data
{
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct rF2Vec3
{
public double x, y, z;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2Wheel
{
[XmlIgnore] public double mSuspensionDeflection; // meters
[XmlIgnore] public double mRideHeight; // meters
[XmlIgnore] public double mSuspForce; // pushrod load in Newtons
public double mBrakeTemp; // Celsius
[XmlIgnore] public double mBrakePressure; // currently 0.0-1.0, depending on driver input and brake balance; will convert to true brake pressure (kPa) in future
public double mRotation; // radians/sec
[XmlIgnore] public double mLateralPatchVel; // lateral velocity at contact patch
[XmlIgnore] public double mLongitudinalPatchVel; // longitudinal velocity at contact patch
[XmlIgnore] public double mLateralGroundVel; // lateral velocity at contact patch
[XmlIgnore] public double mLongitudinalGroundVel; // longitudinal velocity at contact patch
[XmlIgnore] public double mCamber; // radians (positive is left for left-side wheels, right for right-side wheels)
[XmlIgnore] public double mLateralForce; // Newtons
[XmlIgnore] public double mLongitudinalForce; // Newtons
[XmlIgnore] public double mTireLoad; // Newtons
[XmlIgnore] public double mGripFract; // an approximation of what fraction of the contact patch is sliding
public double mPressure; // kPa (tire pressure)
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3)]
public double[] mTemperature; // Kelvin (subtract 273.15 to get Celsius), left/center/right (not to be confused with inside/center/outside!)
public double mWear; // wear (0.0-1.0, fraction of maximum) ... this is not necessarily proportional with grip loss
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 16)]
[XmlIgnore] public byte[] mTerrainName; // the material prefixes from the TDF file
public byte mSurfaceType; // 0=dry, 1=wet, 2=grass, 3=dirt, 4=gravel, 5=rumblestrip, 6=special
public byte mFlat; // whether tire is flat
public byte mDetached; // whether wheel is detached
[XmlIgnore] public double mVerticalTireDeflection;// how much is tire deflected from its (speed-sensitive) radius
[XmlIgnore] public double mWheelYLocation; // wheel's y location relative to vehicle y location
[XmlIgnore] public double mToe; // current toe angle w.r.t. the vehicle
[XmlIgnore] public double mTireCarcassTemperature; // rough average of temperature samples from carcass (Kelvin)
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3)]
[XmlIgnore] public double[] mTireInnerLayerTemperature; // rough average of temperature samples from innermost layer of rubber (before carcass) (Kelvin)
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 24)]
[XmlIgnore] byte[] mExpansion; // for future use
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2VehicleTelemetry
{
// Time
public int mID; // slot ID (note that it can be re-used in multiplayer after someone leaves)
[XmlIgnore] public double mDeltaTime; // time since last update (seconds)
public double mElapsedTime; // game session time
[XmlIgnore] public int mLapNumber; // current lap number
[XmlIgnore] public double mLapStartET; // time this lap was started
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 64)]
[XmlIgnore] public byte[] mVehicleName; // current vehicle name
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 64)]
[XmlIgnore] public byte[] mTrackName; // current track name
// Position and derivatives
public rF2Vec3 mPos; // world position in meters
public rF2Vec3 mLocalVel; // velocity (meters/sec) in local vehicle coordinates
[XmlIgnore] public rF2Vec3 mLocalAccel; // acceleration (meters/sec^2) in local vehicle coordinates
// Orientation and derivatives
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3)]
public rF2Vec3[] mOri; // rows of orientation matrix (use TelemQuat conversions if desired), also converts local
// vehicle vectors into world X, Y, or Z using dot product of rows 0, 1, or 2 respectively
[XmlIgnore] public rF2Vec3 mLocalRot; // rotation (radians/sec) in local vehicle coordinates
[XmlIgnore] public rF2Vec3 mLocalRotAccel; // rotational acceleration (radians/sec^2) in local vehicle coordinates
// Vehicle status
public int mGear; // -1=reverse, 0=neutral, 1+=forward gears
public double mEngineRPM; // engine RPM
public double mEngineWaterTemp; // Celsius
public double mEngineOilTemp; // Celsius
[XmlIgnore] public double mClutchRPM; // clutch RPM
// Driver input
public double mUnfilteredThrottle; // ranges 0.0-1.0
public double mUnfilteredBrake; // ranges 0.0-1.0
[XmlIgnore] public double mUnfilteredSteering; // ranges -1.0-1.0 (left to right)
public double mUnfilteredClutch; // ranges 0.0-1.0
// Filtered input (various adjustments for rev or speed limiting, TC, ABS?, speed sensitive steering, clutch work for semi-automatic shifting, etc.)
[XmlIgnore] public double mFilteredThrottle; // ranges 0.0-1.0
[XmlIgnore] public double mFilteredBrake; // ranges 0.0-1.0
[XmlIgnore] public double mFilteredSteering; // ranges -1.0-1.0 (left to right)
[XmlIgnore] public double mFilteredClutch; // ranges 0.0-1.0
// Misc
[XmlIgnore] public double mSteeringShaftTorque; // torque around steering shaft (used to be mSteeringArmForce, but that is not necessarily accurate for feedback purposes)
[XmlIgnore] public double mFront3rdDeflection; // deflection at front 3rd spring
[XmlIgnore] public double mRear3rdDeflection; // deflection at rear 3rd spring
// Aerodynamics
[XmlIgnore] public double mFrontWingHeight; // front wing height
[XmlIgnore] public double mFrontRideHeight; // front ride height
[XmlIgnore] public double mRearRideHeight; // rear ride height
[XmlIgnore] public double mDrag; // drag
[XmlIgnore] public double mFrontDownforce; // front downforce
[XmlIgnore] public double mRearDownforce; // rear downforce
// State/damage info
public double mFuel; // amount of fuel (liters)
public double mEngineMaxRPM; // rev limit
public byte mScheduledStops; // number of scheduled pitstops
public byte mOverheating; // whether overheating icon is shown
public byte mDetached; // whether any parts (besides wheels) have been detached
[XmlIgnore] public byte mHeadlights; // whether headlights are on
// mDentSeverity is always zero as of 7/3/2017.
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8)]
[XmlIgnore] public byte[] mDentSeverity;// dent severity at 8 locations around the car (0=none, 1=some, 2=more)
public double mLastImpactET; // time of last impact
[XmlIgnore] public double mLastImpactMagnitude; // magnitude of last impact
[XmlIgnore] public rF2Vec3 mLastImpactPos; // location of last impact
// Expanded
[XmlIgnore] public double mEngineTorque; // current engine torque (including additive torque) (used to be mEngineTq, but there's little reason to abbreviate it)
[XmlIgnore] public int mCurrentSector; // the current sector (zero-based) with the pitlane stored in the sign bit (example: entering pits from third sector gives 0x80000002)
public byte mSpeedLimiter; // whether speed limiter is on
[XmlIgnore] public byte mMaxGears; // maximum forward gears
public byte mFrontTireCompoundIndex; // index within brand
[XmlIgnore] public byte mRearTireCompoundIndex; // index within brand
[XmlIgnore] public double mFuelCapacity; // capacity in liters
[XmlIgnore] public byte mFrontFlapActivated; // whether front flap is activated
public byte mRearFlapActivated; // whether rear flap is activated
public byte mRearFlapLegalStatus; // 0=disallowed, 1=criteria detected but not allowed quite yet, 2=allowed
[XmlIgnore] public byte mIgnitionStarter; // 0=off 1=ignition 2=ignition+starter
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 18)]
public byte[] mFrontTireCompoundName; // name of front tire compound
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 18)]
[XmlIgnore] public byte[] mRearTireCompoundName; // name of rear tire compound
public byte mSpeedLimiterAvailable; // whether speed limiter is available
[XmlIgnore] public byte mAntiStallActivated; // whether (hard) anti-stall is activated
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2)]
[XmlIgnore] public byte[] mUnused; //
[XmlIgnore] public float mVisualSteeringWheelRange; // the *visual* steering wheel range
[XmlIgnore] public double mRearBrakeBias; // fraction of brakes on rear
[XmlIgnore] public double mTurboBoostPressure; // current turbo boost pressure if available
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3)]
[XmlIgnore] public float[] mPhysicsToGraphicsOffset; // offset from static CG to graphical center
[XmlIgnore] public float mPhysicalSteeringWheelRange; // the *physical* steering wheel range
// Future use
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 152)]
[XmlIgnore] public byte[] mExpansion; // for future use (note that the slot ID has been moved to mID above)
// keeping this at the end of the structure to make it easier to replace in future versions
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
public rF2Wheel[] mWheels; // wheel info (front left, front right, rear left, rear right)
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2ScoringInfo
{
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] mTrackName; // current track name
public int mSession; // current session (0=testday 1-4=practice 5-8=qual 9=warmup 10-13=race)
public double mCurrentET; // current time
public double mEndET; // ending time
public int mMaxLaps; // maximum laps
public double mLapDist; // distance around track
// MM_NOT_USED
//char *mResultsStream; // results stream additions since last update (newline-delimited and NULL-terminated)
// MM_NEW
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8)]
[XmlIgnore] public byte[] pointer1;
public int mNumVehicles; // current number of vehicles
// Game phases:
// 0 Before session has begun
// 1 Reconnaissance laps (race only)
// 2 Grid walk-through (race only)
// 3 Formation lap (race only)
// 4 Starting-light countdown has begun (race only)
// 5 Green flag
// 6 Full course yellow / safety car
// 7 Session stopped
// 8 Session over
public byte mGamePhase;
// Yellow flag states (applies to full-course only)
// -1 Invalid
// 0 None
// 1 Pending
// 2 Pits closed
// 3 Pit lead lap
// 4 Pits open
// 5 Last lap
// 6 Resume
// 7 Race halt (not currently used)
public sbyte mYellowFlagState;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3)]
public sbyte[] mSectorFlag; // whether there are any local yellows at the moment in each sector (not sure if sector 0 is first or last, so test)
[XmlIgnore] public byte mStartLight; // start light frame (number depends on track)
[XmlIgnore] public byte mNumRedLights; // number of red lights in start sequence
public byte mInRealtime; // in realtime as opposed to at the monitor
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32)]
[XmlIgnore] public byte[] mPlayerName; // player name (including possible multiplayer override)
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 64)]
[XmlIgnore] public byte[] mPlrFileName; // may be encoded to be a legal filename
// weather
[XmlIgnore] public double mDarkCloud; // cloud darkness? 0.0-1.0
public double mRaining; // raining severity 0.0-1.0
public double mAmbientTemp; // temperature (Celsius)
public double mTrackTemp; // temperature (Celsius)
public rF2Vec3 mWind; // wind speed
[XmlIgnore] public double mMinPathWetness; // minimum wetness on main path 0.0-1.0
[XmlIgnore] public double mMaxPathWetness; // maximum wetness on main path 0.0-1.0
// Future use
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
[XmlIgnore] public byte[] mExpansion;
// MM_NOT_USED
// keeping this at the end of the structure to make it easier to replace in future versions
// VehicleScoringInfoV01 *mVehicle; // array of vehicle scoring info's
// MM_NEW
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8)]
[XmlIgnore] public byte[] pointer2;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2VehicleScoring
{
public int mID; // slot ID (note that it can be re-used in multiplayer after someone leaves)
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] mDriverName; // driver name
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 64)]
[XmlIgnore] public byte[] mVehicleName; // vehicle name
public short mTotalLaps; // laps completed
public sbyte mSector; // 0=sector3, 1=sector1, 2=sector2 (don't ask why)
public sbyte mFinishStatus; // 0=none, 1=finished, 2=dnf, 3=dq
public double mLapDist; // current distance around track
public double mPathLateral; // lateral position with respect to *very approximate* "center" path
public double mTrackEdge; // track edge (w.r.t. "center" path) on same side of track as vehicle
public double mBestSector1; // best sector 1
public double mBestSector2; // best sector 2 (plus sector 1)
public double mBestLapTime; // best lap time
public double mLastSector1; // last sector 1
public double mLastSector2; // last sector 2 (plus sector 1)
public double mLastLapTime; // last lap time
public double mCurSector1; // current sector 1 if valid
public double mCurSector2; // current sector 2 (plus sector 1) if valid
// no current laptime because it instantly becomes "last"
public short mNumPitstops; // number of pitstops made
public short mNumPenalties; // number of outstanding penalties
public byte mIsPlayer; // is this the player's vehicle
public sbyte mControl; // who's in control: -1=nobody (shouldn't get this), 0=local player, 1=local AI, 2=remote, 3=replay (shouldn't get this)
public byte mInPits; // between pit entrance and pit exit (not always accurate for remote vehicles)
public byte mPlace; // 1-based position
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] mVehicleClass; // vehicle class
// Dash Indicators
public double mTimeBehindNext; // time behind vehicle in next higher place
[XmlIgnore] public int mLapsBehindNext; // laps behind vehicle in next higher place
[XmlIgnore] public double mTimeBehindLeader; // time behind leader
[XmlIgnore] public int mLapsBehindLeader; // laps behind leader
public double mLapStartET; // time this lap was started
// Position and derivatives
[XmlIgnore] public rF2Vec3 mPos; // world position in meters
// TODO: remove these serialization, once we use telemetry
public rF2Vec3 mLocalVel; // velocity (meters/sec) in local vehicle coordinates
public rF2Vec3 mLocalAccel; // acceleration (meters/sec^2) in local vehicle coordinates
// Orientation and derivatives
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3)]
[XmlIgnore] public rF2Vec3[] mOri; // rows of orientation matrix (use TelemQuat conversions if desired), also converts local
// vehicle vectors into world X, Y, or Z using dot product of rows 0, 1, or 2 respectively
[XmlIgnore] public rF2Vec3 mLocalRot; // rotation (radians/sec) in local vehicle coordinates
[XmlIgnore] public rF2Vec3 mLocalRotAccel; // rotational acceleration (radians/sec^2) in local vehicle coordinates
// tag.2012.03.01 - stopped casting some of these so variables now have names and mExpansion has shrunk, overall size and old data locations should be same
[XmlIgnore] public byte mHeadlights; // status of headlights
public byte mPitState; // 0=none, 1=request, 2=entering, 3=stopped, 4=exiting
[XmlIgnore] public byte mServerScored; // whether this vehicle is being scored by server (could be off in qualifying or racing heats)
[XmlIgnore] public byte mIndividualPhase;// game phases (described below) plus 9=after formation, 10=under yellow, 11=under blue (not used)
[XmlIgnore] public int mQualification; // 1-based, can be -1 when invalid
[XmlIgnore] public double mTimeIntoLap; // estimated time into lap
[XmlIgnore] public double mEstimatedLapTime; // estimated laptime used for 'time behind' and 'time into lap' (note: this may changed based on vehicle and setup!?)
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 24)]
[XmlIgnore] public byte[] mPitGroup; // pit group (same as team name unless pit is shared)
public byte mFlag; // primary flag being shown to vehicle (currently only 0=green or 6=blue)
[XmlIgnore] public byte mUnderYellow; // whether this car has taken a full-course caution flag at the start/finish line
public byte mCountLapFlag; // 0 = do not count lap or time, 1 = count lap but not time, 2 = count lap and time
public byte mInGarageStall; // appears to be within the correct garage stall
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 16)]
[XmlIgnore] public byte[] mUpgradePack; // Coded upgrades
// Future use
// tag.2012.04.06 - SEE ABOVE!
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 60)]
[XmlIgnore] public byte[] mExpansion; // for future use
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2PhysicsOptions
{
[XmlIgnore] public byte mTractionControl; // 0 (off) - 3 (high)
[XmlIgnore] public byte mAntiLockBrakes; // 0 (off) - 2 (high)
[XmlIgnore] public byte mStabilityControl; // 0 (off) - 2 (high)
[XmlIgnore] public byte mAutoShift; // 0 (off), 1 (upshifts), 2 (downshifts), 3 (all)
[XmlIgnore] public byte mAutoClutch; // 0 (off), 1 (on)
public byte mInvulnerable; // 0 (off), 1 (on)
[XmlIgnore] public byte mOppositeLock; // 0 (off), 1 (on)
[XmlIgnore] public byte mSteeringHelp; // 0 (off) - 3 (high)
[XmlIgnore] public byte mBrakingHelp; // 0 (off) - 2 (high)
[XmlIgnore] public byte mSpinRecovery; // 0 (off), 1 (on)
[XmlIgnore] public byte mAutoPit; // 0 (off), 1 (on)
[XmlIgnore] public byte mAutoLift; // 0 (off), 1 (on)
[XmlIgnore] public byte mAutoBlip; // 0 (off), 1 (on)
public byte mFuelMult; // fuel multiplier (0x-7x)
[XmlIgnore] public byte mTireMult; // tire wear multiplier (0x-7x)
[XmlIgnore] public byte mMechFail; // mechanical failure setting; 0 (off), 1 (normal), 2 (timescaled)
[XmlIgnore] public byte mAllowPitcrewPush; // 0 (off), 1 (on)
[XmlIgnore] public byte mRepeatShifts; // accidental repeat shift prevention (0-5; see PLR file)
[XmlIgnore] public byte mHoldClutch; // for auto-shifters at start of race: 0 (off), 1 (on)
[XmlIgnore] public byte mAutoReverse; // 0 (off), 1 (on)
[XmlIgnore] public byte mAlternateNeutral; // Whether shifting up and down simultaneously equals neutral
// tag.2014.06.09 - yes these are new, but no they don't change the size of the structure nor the address of the other variables in it (because we're just using the existing padding)
[XmlIgnore] public byte mAIControl; // Whether player vehicle is currently under AI control
[XmlIgnore] public byte mUnused1; //
[XmlIgnore] public byte mUnused2; //
[XmlIgnore] public float mManualShiftOverrideTime; // time before auto-shifting can resume after recent manual shift
[XmlIgnore] public float mAutoShiftOverrideTime; // time before manual shifting can resume after recent auto shift
[XmlIgnore] public float mSpeedSensitiveSteering; // 0.0 (off) - 1.0
[XmlIgnore] public float mSteerRatioSpeed; // speed (m/s) under which lock gets expanded to full
}
//////////////////////////////////////////////////////////////////////////////////////////
// Identical to TrackRulesCommandV01, except where noted by MM_NEW/MM_NOT_USED comments. Renamed to match plugin convention.
//////////////////////////////////////////////////////////////////////////////////////////
public enum rF2TrackRulesCommand
{
AddFromTrack = 0, // crossed s/f line for first time after full-course yellow was called
AddFromPit, // exited pit during full-course yellow
AddFromUndq, // during a full-course yellow, the admin reversed a disqualification
RemoveToPit, // entered pit during full-course yellow
RemoveToDnf, // vehicle DNF'd during full-course yellow
RemoveToDq, // vehicle DQ'd during full-course yellow
RemoveToUnloaded, // vehicle unloaded (possibly kicked out or banned) during full-course yellow
MoveToBack, // misbehavior during full-course yellow, resulting in the penalty of being moved to the back of their current line
LongestTime, // misbehavior during full-course yellow, resulting in the penalty of being moved to the back of the longest line
//------------------
Maximum // should be last
}
//////////////////////////////////////////////////////////////////////////////////////////
// Identical to TrackRulesActionV01, except where noted by MM_NEW/MM_NOT_USED comments.
//////////////////////////////////////////////////////////////////////////////////////////
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct rF2TrackRulesAction
{
// input only
[XmlIgnore] public rF2TrackRulesCommand mCommand; // recommended action
[XmlIgnore] public int mID; // slot ID if applicable
[XmlIgnore] public double mET; // elapsed time that event occurred, if applicable
}
//////////////////////////////////////////////////////////////////////////////////////////
// Identical to TrackRulesColumnV01, except where noted by MM_NEW/MM_NOT_USED comments. Renamed to match plugin convention.
//////////////////////////////////////////////////////////////////////////////////////////
public enum rF2TrackRulesColumn
{
LeftLane = 0, // left (inside)
MidLefLane, // mid-left
MiddleLane, // middle
MidrRghtLane, // mid-right
RightLane, // right (outside)
//------------------
MaxLanes, // should be after the valid static lane choices
//------------------
Invalid = MaxLanes, // currently invalid (hasn't crossed line or in pits/garage)
FreeChoice, // free choice (dynamically chosen by driver)
Pending, // depends on another participant's free choice (dynamically set after another driver chooses)
//------------------
Maximum // should be last
}
//////////////////////////////////////////////////////////////////////////////////////////
// Identical to TrackRulesParticipantV01, except where noted by MM_NEW/MM_NOT_USED comments.
//////////////////////////////////////////////////////////////////////////////////////////
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2TrackRulesParticipant
{
// input only
public int mID; // slot ID
[XmlIgnore] public short mFrozenOrder; // 0-based place when caution came out (not valid for formation laps)
public short mPlace; // 1-based place (typically used for the initialization of the formation lap track order)
[XmlIgnore] public float mYellowSeverity; // a rating of how much this vehicle is contributing to a yellow flag (the sum of all vehicles is compared to TrackRulesV01::mSafetyCarThreshold)
[XmlIgnore] public double mCurrentRelativeDistance; // equal to ( ( ScoringInfoV01::mLapDist * this->mRelativeLaps ) + VehicleScoringInfoV01::mLapDist )
// input/output
public int mRelativeLaps; // current formation/caution laps relative to safety car (should generally be zero except when safety car crosses s/f line); this can be decremented to implement 'wave around' or 'beneficiary rule' (a.k.a. 'lucky dog' or 'free pass')
public rF2TrackRulesColumn mColumnAssignment;// which column (line/lane) that participant is supposed to be in
public int mPositionAssignment; // 0-based position within column (line/lane) that participant is supposed to be located at (-1 is invalid)
public byte mAllowedToPit; // whether the rules allow this particular vehicle to enter pits right now
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3)]
[XmlIgnore] public byte[] mUnused; //
[XmlIgnore] public double mGoalRelativeDistance; // calculated based on where the leader is, and adjusted by the desired column spacing and the column/position assignments
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 96)]
public byte[] mMessage; // a message for this participant to explain what is going on (untranslated; it will get run through translator on client machines)
// future expansion
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 192)]
[XmlIgnore] public byte[] mExpansion;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Identical to TrackRulesStageV01, except where noted by MM_NEW/MM_NOT_USED comments. Renamed to match plugin convention.
//////////////////////////////////////////////////////////////////////////////////////////
public enum rF2TrackRulesStage
{
FormationInit = 0, // initialization of the formation lap
FormationUpdate, // update of the formation lap
Normal, // normal (non-yellow) update
CautionInit, // initialization of a full-course yellow
CautionUpdate, // update of a full-course yellow
//------------------
Maximum // should be last
}
//////////////////////////////////////////////////////////////////////////////////////////
// Identical to TrackRulesV01, except where noted by MM_NEW/MM_NOT_USED comments.
//////////////////////////////////////////////////////////////////////////////////////////
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2TrackRules
{
// input only
[XmlIgnore] public double mCurrentET; // current time
public rF2TrackRulesStage mStage; // current stage
public rF2TrackRulesColumn mPoleColumn; // column assignment where pole position seems to be located
[XmlIgnore] public int mNumActions; // number of recent actions
// MM_NOT_USED
// TrackRulesActionV01 *mAction; // array of recent actions
// MM_NEW
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8)]
[XmlIgnore] public byte[] pointer1;
public int mNumParticipants; // number of participants (vehicles)
[XmlIgnore] public byte mYellowFlagDetected; // whether yellow flag was requested or sum of participant mYellowSeverity's exceeds mSafetyCarThreshold
[XmlIgnore] public byte mYellowFlagLapsWasOverridden; // whether mYellowFlagLaps (below) is an admin request
[XmlIgnore] public byte mSafetyCarExists; // whether safety car even exists
public byte mSafetyCarActive; // whether safety car is active
public int mSafetyCarLaps; // number of laps
[XmlIgnore] public float mSafetyCarThreshold; // the threshold at which a safety car is called out (compared to the sum of TrackRulesParticipantV01::mYellowSeverity for each vehicle)
public double mSafetyCarLapDist; // safety car lap distance
[XmlIgnore] public float mSafetyCarLapDistAtStart; // where the safety car starts from
public float mPitLaneStartDist; // where the waypoint branch to the pits breaks off (this may not be perfectly accurate)
[XmlIgnore] public float mTeleportLapDist; // the front of the teleport locations (a useful first guess as to where to throw the green flag)
// future input expansion
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
[XmlIgnore] public byte[] mInputExpansion;
// input/output
[XmlIgnore] public sbyte mYellowFlagState; // see ScoringInfoV01 for values
[XmlIgnore] public short mYellowFlagLaps; // suggested number of laps to run under yellow (may be passed in with admin command)
[XmlIgnore] public int mSafetyCarInstruction; // 0=no change, 1=go active, 2=head for pits
public float mSafetyCarSpeed; // maximum speed at which to drive
[XmlIgnore] public float mSafetyCarMinimumSpacing; // minimum spacing behind safety car (-1 to indicate no limit)
[XmlIgnore] public float mSafetyCarMaximumSpacing; // maximum spacing behind safety car (-1 to indicate no limit)
[XmlIgnore] public float mMinimumColumnSpacing; // minimum desired spacing between vehicles in a column (-1 to indicate indeterminate/unenforced)
[XmlIgnore] public float mMaximumColumnSpacing; // maximum desired spacing between vehicles in a column (-1 to indicate indeterminate/unenforced)
[XmlIgnore] public float mMinimumSpeed; // minimum speed that anybody should be driving (-1 to indicate no limit)
[XmlIgnore] public float mMaximumSpeed; // maximum speed that anybody should be driving (-1 to indicate no limit)
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 96)]
public byte[] mMessage; // a message for everybody to explain what is going on (which will get run through translator on client machines)
// MM_NOT_USED
// TrackRulesParticipantV01 *mParticipant; // array of partipants (vehicles)
// MM_NEW
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8)]
[XmlIgnore] public byte[] pointer2;
// future input/output expansion
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
[XmlIgnore] public byte[] mInputOutputExpansion;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2MappedBufferVersionBlock
{
// If both version variables are equal, buffer is not being written to, or we're extremely unlucky and second check is necessary.
// If versions don't match, buffer is being written to, or is incomplete (game crash, or missed transition).
[XmlIgnore] public uint mVersionUpdateBegin; // Incremented right before buffer is written to.
[XmlIgnore] public uint mVersionUpdateEnd; // Incremented after buffer write is done.
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2MappedBufferVersionBlockWithSize
{
[XmlIgnore] public uint mVersionUpdateBegin; // Incremented right before buffer is written to.
[XmlIgnore] public uint mVersionUpdateEnd; // Incremented after buffer write is done.
[XmlIgnore] public int mBytesUpdatedHint; // How many bytes of the structure were written during the last update.
// 0 means unknown (whole buffer should be considered as updated).
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2Telemetry
{
[XmlIgnore] public uint mVersionUpdateBegin; // Incremented right before buffer is written to.
[XmlIgnore] public uint mVersionUpdateEnd; // Incremented after buffer write is done.
[XmlIgnore] public int mBytesUpdatedHint; // How many bytes of the structure were written during the last update.
// 0 means unknown (whole buffer should be considered as updated).
public int mNumVehicles; // current number of vehicles
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = rFactor2Constants.MAX_MAPPED_VEHICLES)]
public rF2VehicleTelemetry[] mVehicles;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2Scoring
{
[XmlIgnore] public uint mVersionUpdateBegin; // Incremented right before buffer is written to.
[XmlIgnore] public uint mVersionUpdateEnd; // Incremented after buffer write is done.
[XmlIgnore] public int mBytesUpdatedHint; // How many bytes of the structure were written during the last update.
public rF2ScoringInfo mScoringInfo;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = rFactor2Constants.MAX_MAPPED_VEHICLES)]
public rF2VehicleScoring[] mVehicles;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2Rules
{
[XmlIgnore] public uint mVersionUpdateBegin; // Incremented right before buffer is written to.
[XmlIgnore] public uint mVersionUpdateEnd; // Incremented after buffer write is done.
[XmlIgnore] public int mBytesUpdatedHint; // How many bytes of the structure were written during the last update.
public rF2TrackRules mTrackRules;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = rFactor2Constants.MAX_MAPPED_VEHICLES)]
[XmlIgnore] public rF2TrackRulesAction[] mActions;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = rFactor2Constants.MAX_MAPPED_VEHICLES)]
public rF2TrackRulesParticipant[] mParticipants;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct rF2TrackedDamage
{
public double mMaxImpactMagnitude; // Max impact magnitude. Tracked on every telemetry update, and reset on visit to pits or Session restart.
public double mAccumulatedImpactMagnitude; // Accumulated impact magnitude. Tracked on every telemetry update, and reset on visit to pits or Session restart.
};
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct rF2VehScoringCapture
{
// VehicleScoringInfoV01 members:
public int mID; // slot ID (note that it can be re-used in multiplayer after someone leaves)
public byte mPlace;
public byte mIsPlayer;
[XmlIgnore] public sbyte mFinishStatus; // 0=none, 1=finished, 2=dnf, 3=dq
};
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct rF2SessionTransitionCapture
{
// ScoringInfoV01 members:
[XmlIgnore] public byte mGamePhase;
[XmlIgnore] public int mSession;
// VehicleScoringInfoV01 members:
public int mNumScoringVehicles;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = rFactor2Constants.MAX_MAPPED_VEHICLES)]
public rF2VehScoringCapture[] mScoringVehicles;
};
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct rF2HostedPluginVars
{
public byte StockCarRules_IsHosted; // Is StockCarRules.dll successfully loaded into SM plugin?
public int StockCarRules_DoubleFileType; // DoubleFileType plugin variable value.
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct rF2Extended
{
[XmlIgnore] public uint mVersionUpdateBegin; // Incremented right before buffer is written to.
[XmlIgnore] public uint mVersionUpdateEnd; // Incremented after buffer write is done.
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] mVersion; // API version
public byte is64bit; // Is 64bit plugin?
// Physics options (updated on session start):
public rF2PhysicsOptions mPhysics;
// Damage tracking for each vehicle (indexed by mID % rF2MappedBufferHeader::MAX_MAPPED_IDS):
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = rFactor2Constants.MAX_MAPPED_IDS)]
public rF2TrackedDamage[] mTrackedDamages;
// Function call based flags:
public byte mInRealtimeFC; // in realtime as opposed to at the monitor (reported via last EnterRealtime/ExitRealtime calls).
[XmlIgnore] public byte mMultimediaThreadStarted; // multimedia thread started (reported via ThreadStarted/ThreadStopped calls).
[XmlIgnore] public byte mSimulationThreadStarted; // simulation thread started (reported via ThreadStarted/ThreadStopped calls).
public byte mSessionStarted; // Set to true on Session Started, set to false on Session Ended.
[XmlIgnore] public Int64 mTicksSessionStarted; // Ticks when session started.
public Int64 mTicksSessionEnded; // Ticks when session ended.
public rF2SessionTransitionCapture mSessionTransitionCapture; // Contains partial internals capture at session transition time.
// Captured non-empty MessageInfoV01::mText message.
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] mDisplayedMessageUpdateCapture;
public rF2HostedPluginVars mHostedPluginVars;
}
}
}

View file

@ -1,70 +0,0 @@
use anyhow::Error as AnyError;
use std::mem;
use crate::rfactor_structs::*;
pub const MM_TELEMETRY_FILE_NAME: &str = "$rFactor2SMMP_Telemetry$";
pub const MM_SCORING_FILE_NAME: &str = "$rFactor2SMMP_Scoring$";
pub const MM_EXTENDED_FILE_NAME: &str = "$rFactor2SMMP_Extended$";
pub const MM_PITINFO_FILE_NAME: &str = "$rFactor2SMMP_PitInfo$";
pub const MM_WEATHER_FILE_NAME: &str = "$rFactor2SMMP_Weather$";
pub const MM_RULES_CONTROL_FILE_NAME: &str = "$rFactor2SMMP_RulesControl$";
pub const MAX_MAPPED_VEHICLES: usize = 128;
pub const MAX_MAPPED_IDS: usize = 512;
#[repr(C, packed(4))]
#[derive(Debug, Copy, Clone)]
pub struct rF2Telemetry {
pub version_update_begin: u32,
pub version_update_end: u32,
pub bytes_update_hint: i32,
pub num_vehicles: i32,
pub vehicle_telemetry: [TelemInfoV01; MAX_MAPPED_VEHICLES],
}
impl rF2Telemetry {
pub const SIZE: usize = mem::size_of::<Self>();
pub fn vehicles(&self) -> &[TelemInfoV01] {
&self.vehicle_telemetry[0..self.num_vehicles as usize]
}
}
impl TryFrom<&[u8]> for rF2Telemetry {
type Error = AnyError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
debug_assert!(value.len() == Self::SIZE);
let fixed_size: [u8; Self::SIZE] = value.try_into().unwrap();
Ok(unsafe { mem::transmute(fixed_size) })
}
}
#[repr(C, packed(4))]
#[derive(Debug, Copy, Clone)]
pub struct rF2Scoring {
pub version_update_begin: u32,
pub version_update_end: u32,
pub bytes_update_hint: i32,
pub scoring_info: ScoringInfoV01,
pub vehicles: [VehicleScoringInfoV01; MAX_MAPPED_VEHICLES],
}
impl rF2Scoring {
pub const SIZE: usize = mem::size_of::<Self>();
}
impl TryFrom<&[u8]> for rF2Scoring {
type Error = AnyError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
debug_assert!(value.len() == Self::SIZE);
let fixed_size: [u8; Self::SIZE] = value.try_into().unwrap();
Ok(unsafe { mem::transmute(fixed_size) })
}
}

View file

@ -1,36 +1,36 @@
mod additional_rfactor;
#[allow(warnings)] #[allow(warnings)]
mod rfactor_structs; mod rfactor_structs;
use std::{fs::File, path::Path}; use std::{fs::File, path::Path};
use additional_rfactor::*;
use anyhow::Result; use anyhow::Result;
use memmap2::Mmap; use memmap2::Mmap;
use rfactor_structs::TelemInfoV01;
const MM_TELEMETRY_FILE_NAME: &str = "$rFactor2SMMP_Telemetry$";
const MM_SCORING_FILE_NAME: &str = "$rFactor2SMMP_Scoring$";
const MM_RULES_FILE_NAME: &str = "$rFactor2SMMP_Rules$";
const MM_FORCE_FEEDBACK_FILE_NAME: &str = "$rFactor2SMMP_ForceFeedback$";
const MM_GRAPHICS_FILE_NAME: &str = "$rFactor2SMMP_Graphics$";
const MM_PITINFO_FILE_NAME: &str = "$rFactor2SMMP_PitInfo$";
const MM_WEATHER_FILE_NAME: &str = "$rFactor2SMMP_Weather$";
const MM_EXTENDED_FILE_NAME: &str = "$rFactor2SMMP_Extended$";
const MM_HWCONTROL_FILE_NAME: &str = "$rFactor2SMMP_HWControl$";
const MM_HWCONTROL_LAYOUT_VERSION: u32 = 1;
const MM_WEATHER_CONTROL_FILE_NAME: &str = "$rFactor2SMMP_WeatherControl$";
const MM_WEATHER_CONTROL_LAYOUT_VERSION: u32 = 1;
const MM_RULES_CONTROL_FILE_NAME: &str = "$rFactor2SMMP_RulesControl$";
const MM_RULES_CONTROL_LAYOUT_VERSION: u32 = 1;
const MM_PLUGIN_CONTROL_FILE_NAME: &str = "$rFactor2SMMP_PluginControl$";
const RFACTOR_SHM_FILE: &str = "/dev/shm"; const RFACTOR_SHM_FILE: &str = "/dev/shm";
pub struct TelemetryReader { pub fn test_read() -> Result<()> {
_telemetry_file: File, let file = File::open(Path::new(RFACTOR_SHM_FILE).join(MM_TELEMETRY_FILE_NAME))?;
shm: Mmap, let mmap = unsafe { Mmap::map(&file)? };
}
Ok(())
impl TelemetryReader {
pub fn new() -> Result<Self> {
let file = File::open(Path::new(RFACTOR_SHM_FILE).join(MM_TELEMETRY_FILE_NAME))?;
let mmap = unsafe { Mmap::map(&file)? };
Ok(Self {
_telemetry_file: file,
shm: mmap,
})
}
pub fn query_telemetry(&self) -> Result<Vec<TelemInfoV01>> {
let telemetry = rF2Telemetry::try_from(&self.shm[0..rF2Telemetry::SIZE])?;
let vehicles = telemetry.vehicles();
Ok(vehicles.to_vec())
}
} }