From 5e07bfa54a7255346f3db1a49a164e0dd9a6bb9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20H=C3=BCbner?= Date: Wed, 9 Feb 2022 14:27:02 +0100 Subject: [PATCH] Initial commit --- .gitignore | 86 ++++ .vscode/settings.json | 23 + Include/Example.hpp | 82 +++ Include/InternalsPlugin.hpp | 958 +++++++++++++++++++++++++++++++++++ Include/PluginObjects.hpp | 82 +++ Include/RFServer.hpp | 43 ++ Include/Socket.hpp | 92 ++++ Source/Example.cpp | 383 ++++++++++++++ Source/RFServer.cpp | 238 +++++++++ VC11/InternalsPlugin.sln | 26 + VC11/InternalsPlugin.vcxproj | 282 +++++++++++ 11 files changed, 2295 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Include/Example.hpp create mode 100644 Include/InternalsPlugin.hpp create mode 100644 Include/PluginObjects.hpp create mode 100644 Include/RFServer.hpp create mode 100644 Include/Socket.hpp create mode 100644 Source/Example.cpp create mode 100644 Source/RFServer.cpp create mode 100644 VC11/InternalsPlugin.sln create mode 100644 VC11/InternalsPlugin.vcxproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..12655d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,86 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/c++,windows,visualstudiocode +# Edit at https://www.toptal.com/developers/gitignore?templates=c++,windows,visualstudiocode + +### C++ ### +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# Support for Project snippet scope + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/c++,windows,visualstudiocode diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..49336e4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + "files.associations": { + "cmath": "cpp", + "bit": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "cwchar": "cpp", + "exception": "cpp", + "initializer_list": "cpp", + "limits": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "xstddef": "cpp", + "xtr1common": "cpp", + "xutility": "cpp", + "xstring": "cpp" + } +} \ No newline at end of file diff --git a/Include/Example.hpp b/Include/Example.hpp new file mode 100644 index 0000000..97d8b10 --- /dev/null +++ b/Include/Example.hpp @@ -0,0 +1,82 @@ +//ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +//Ý Þ +//Ý Module: Internals Example Header File Þ +//Ý Þ +//Ý Description: Declarations for the Internals Example Plugin Þ +//Ý Þ +//Ý Þ +//Ý This source code module, and all information, data, and algorithms Þ +//Ý associated with it, are part of CUBE technology (tm). Þ +//Ý PROPRIETARY AND CONFIDENTIAL Þ +//Ý Copyright (c) 1996-2014 Image Space Incorporated. All rights reserved. Þ +//Ý Þ +//Ý Þ +//Ý Change history: Þ +//Ý tag.2005.11.30: created Þ +//Ý Þ +//ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +#ifndef _INTERNALS_EXAMPLE_H +#define _INTERNALS_EXAMPLE_H + +#include "InternalsPlugin.hpp" + + +// This is used for the app to use the plugin for its intended purpose +class ExampleInternalsPlugin : public InternalsPluginV01 // REMINDER: exported function GetPluginVersion() should return 1 if you are deriving from this InternalsPluginV01, 2 for InternalsPluginV02, etc. +{ + + public: + + // Constructor/destructor + ExampleInternalsPlugin() {} + ~ExampleInternalsPlugin() {} + + // These are the functions derived from base class InternalsPlugin + // that can be implemented. + void Startup( long version ); // game startup + void Shutdown(); // game shutdown + + void EnterRealtime(); // entering realtime + void ExitRealtime(); // exiting realtime + + void StartSession(); // session has started + void EndSession(); // session has ended + + // GAME OUTPUT + long WantsTelemetryUpdates() { return( 1 ); } // CHANGE TO 1 TO ENABLE TELEMETRY EXAMPLE! + void UpdateTelemetry( const TelemInfoV01 &info ); + + bool WantsGraphicsUpdates() { return( false ); } // CHANGE TO TRUE TO ENABLE GRAPHICS EXAMPLE! + void UpdateGraphics( const GraphicsInfoV01 &info ); + + // GAME INPUT + bool HasHardwareInputs() { return( false ); } // CHANGE TO TRUE TO ENABLE HARDWARE EXAMPLE! + void UpdateHardware( const double fDT ) { mET += fDT; } // update the hardware with the time between frames + void EnableHardware() { mEnabled = true; } // message from game to enable hardware + void DisableHardware() { mEnabled = false; } // message from game to disable hardware + + // See if the plugin wants to take over a hardware control. If the plugin takes over the + // control, this method returns true and sets the value of the double pointed to by the + // second arg. Otherwise, it returns false and leaves the double unmodified. + bool CheckHWControl( const char * const controlName, double &fRetVal ); + + bool ForceFeedback( double &forceValue ); // SEE FUNCTION BODY TO ENABLE FORCE EXAMPLE + + // SCORING OUTPUT + bool WantsScoringUpdates() { return( false ); } // CHANGE TO TRUE TO ENABLE SCORING EXAMPLE! + void UpdateScoring( const ScoringInfoV01 &info ); + + // COMMENTARY INPUT + bool RequestCommentary( CommentaryRequestInfoV01 &info ); // SEE FUNCTION BODY TO ENABLE COMMENTARY EXAMPLE + + private: + + void WriteToAllExampleOutputFiles( const char * const openStr, const char * const msg ); + double mET; // needed for the hardware example + bool mEnabled; // needed for the hardware example +}; + + +#endif // _INTERNALS_EXAMPLE_H + diff --git a/Include/InternalsPlugin.hpp b/Include/InternalsPlugin.hpp new file mode 100644 index 0000000..c1edc4f --- /dev/null +++ b/Include/InternalsPlugin.hpp @@ -0,0 +1,958 @@ +//��������������������������������������������������������������������������� +//� � +//� Module: Header file for internals plugin � +//� � +//� Description: Interface declarations for internals plugin � +//� � +//� This source code module, and all information, data, and algorithms � +//� associated with it, are part of isiMotor Technology (tm). � +//� PROPRIETARY AND CONFIDENTIAL � +//� Copyright (c) 1996-2015 Image Space Incorporated. All rights reserved. � +//� � +//� Change history: � +//� tag.2005.11.29: created � +//� � +//��������������������������������������������������������������������������� + +#ifndef _INTERNALS_PLUGIN_HPP_ +#define _INTERNALS_PLUGIN_HPP_ + +#include "PluginObjects.hpp" // base class for plugin objects to derive from +// #include // for sqrt() +// #include // for HWND + +struct HWND +{ + int d; +}; + +double sqrt(double d) { + return d; +} + +// rF and plugins must agree on structure packing, so set it explicitly here ... whatever the current +// packing is will be restored at the end of this include with another #pragma. +#pragma pack(push, 4) + +//������������������������������������������������������������������������Ŀ +//� Version01 Structures � +//�������������������������������������������������������������������������� + +struct TelemVect3 +{ + double x, y, z; + + void Set(const double a, const double b, const double c) + { + x = a; + y = b; + z = c; + } + + // Allowed to reference as [0], [1], or [2], instead of .x, .y, or .z, respectively + double &operator[](long i) { return ((&x)[i]); } + const double &operator[](long i) const { return ((&x)[i]); } +}; + +struct TelemQuat +{ + double w, x, y, z; + + // Convert this quaternion to a matrix + void ConvertQuatToMat(TelemVect3 ori[3]) const + { + const double x2 = x + x; + const double xx = x * x2; + const double y2 = y + y; + const double yy = y * y2; + const double z2 = z + z; + const double zz = z * z2; + const double xz = x * z2; + const double xy = x * y2; + const double wy = w * y2; + const double wx = w * x2; + const double wz = w * z2; + const double yz = y * z2; + ori[0][0] = (double)1.0 - (yy + zz); + ori[0][1] = xy - wz; + ori[0][2] = xz + wy; + ori[1][0] = xy + wz; + ori[1][1] = (double)1.0 - (xx + zz); + ori[1][2] = yz - wx; + ori[2][0] = xz - wy; + ori[2][1] = yz + wx; + ori[2][2] = (double)1.0 - (xx + yy); + } + + // Convert a matrix to this quaternion + void ConvertMatToQuat(const TelemVect3 ori[3]) + { + const double trace = ori[0][0] + ori[1][1] + ori[2][2] + (double)1.0; + if (trace > 0.0625f) + { + const double sqrtTrace = sqrt(trace); + const double s = (double)0.5 / sqrtTrace; + w = (double)0.5 * sqrtTrace; + x = (ori[2][1] - ori[1][2]) * s; + y = (ori[0][2] - ori[2][0]) * s; + z = (ori[1][0] - ori[0][1]) * s; + } + else if ((ori[0][0] > ori[1][1]) && (ori[0][0] > ori[2][2])) + { + const double sqrtTrace = sqrt((double)1.0 + ori[0][0] - ori[1][1] - ori[2][2]); + const double s = (double)0.5 / sqrtTrace; + w = (ori[2][1] - ori[1][2]) * s; + x = (double)0.5 * sqrtTrace; + y = (ori[0][1] + ori[1][0]) * s; + z = (ori[0][2] + ori[2][0]) * s; + } + else if (ori[1][1] > ori[2][2]) + { + const double sqrtTrace = sqrt((double)1.0 + ori[1][1] - ori[0][0] - ori[2][2]); + const double s = (double)0.5 / sqrtTrace; + w = (ori[0][2] - ori[2][0]) * s; + x = (ori[0][1] + ori[1][0]) * s; + y = (double)0.5 * sqrtTrace; + z = (ori[1][2] + ori[2][1]) * s; + } + else + { + const double sqrtTrace = sqrt((double)1.0 + ori[2][2] - ori[0][0] - ori[1][1]); + const double s = (double)0.5 / sqrtTrace; + w = (ori[1][0] - ori[0][1]) * s; + x = (ori[0][2] + ori[2][0]) * s; + y = (ori[1][2] + ori[2][1]) * s; + z = (double)0.5 * sqrtTrace; + } + } +}; + +struct TelemWheelV01 +{ + double mSuspensionDeflection; // meters + double mRideHeight; // meters + double mSuspForce; // pushrod load in Newtons + double mBrakeTemp; // Celsius + double mBrakePressure; // currently 0.0-1.0, depending on driver input and brake balance; will convert to true brake pressure (kPa) in future + + double mRotation; // radians/sec + double mLateralPatchVel; // lateral velocity at contact patch + double mLongitudinalPatchVel; // longitudinal velocity at contact patch + double mLateralGroundVel; // lateral velocity at contact patch + double mLongitudinalGroundVel; // longitudinal velocity at contact patch + double mCamber; // radians (positive is left for left-side wheels, right for right-side wheels) + double mLateralForce; // Newtons + double mLongitudinalForce; // Newtons + double mTireLoad; // Newtons + + double mGripFract; // an approximation of what fraction of the contact patch is sliding + double mPressure; // kPa (tire pressure) + double mTemperature[3]; // Kelvin (subtract 273.15 to get Celsius), left/center/right (not to be confused with inside/center/outside!) + double mWear; // wear (0.0-1.0, fraction of maximum) ... this is not necessarily proportional with grip loss + char mTerrainName[16]; // the material prefixes from the TDF file + unsigned char mSurfaceType; // 0=dry, 1=wet, 2=grass, 3=dirt, 4=gravel, 5=rumblestrip, 6=special + bool mFlat; // whether tire is flat + bool mDetached; // whether wheel is detached + + double mVerticalTireDeflection; // how much is tire deflected from its (speed-sensitive) radius + double mWheelYLocation; // wheel's y location relative to vehicle y location + double mToe; // current toe angle w.r.t. the vehicle + + double mTireCarcassTemperature; // rough average of temperature samples from carcass (Kelvin) + double mTireInnerLayerTemperature[3]; // rough average of temperature samples from innermost layer of rubber (before carcass) (Kelvin) + + unsigned char mExpansion[24]; // for future use +}; + +// Our world coordinate system is left-handed, with +y pointing up. +// The local vehicle coordinate system is as follows: +// +x points out the left side of the car (from the driver's perspective) +// +y points out the roof +// +z points out the back of the car +// Rotations are as follows: +// +x pitches up +// +y yaws to the right +// +z rolls to the right +// Note that ISO vehicle coordinates (+x forward, +y right, +z upward) are +// right-handed. If you are using that system, be sure to negate any rotation +// or torque data because things rotate in the opposite direction. In other +// words, a -z velocity in rFactor is a +x velocity in ISO, but a -z rotation +// in rFactor is a -x rotation in ISO!!! + +struct TelemInfoV01 +{ + // Time + long mID; // slot ID (note that it can be re-used in multiplayer after someone leaves) + double mDeltaTime; // time since last update (seconds) + double mElapsedTime; // game session time + long mLapNumber; // current lap number + double mLapStartET; // time this lap was started + char mVehicleName[64]; // current vehicle name + char mTrackName[64]; // current track name + + // Position and derivatives + TelemVect3 mPos; // world position in meters + TelemVect3 mLocalVel; // velocity (meters/sec) in local vehicle coordinates + TelemVect3 mLocalAccel; // acceleration (meters/sec^2) in local vehicle coordinates + + // Orientation and derivatives + TelemVect3 mOri[3]; // 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 + TelemVect3 mLocalRot; // rotation (radians/sec) in local vehicle coordinates + TelemVect3 mLocalRotAccel; // rotational acceleration (radians/sec^2) in local vehicle coordinates + + // Vehicle status + long mGear; // -1=reverse, 0=neutral, 1+=forward gears + double mEngineRPM; // engine RPM + double mEngineWaterTemp; // Celsius + double mEngineOilTemp; // Celsius + double mClutchRPM; // clutch RPM + + // Driver input + double mUnfilteredThrottle; // ranges 0.0-1.0 + double mUnfilteredBrake; // ranges 0.0-1.0 + double mUnfilteredSteering; // ranges -1.0-1.0 (left to right) + 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.) + double mFilteredThrottle; // ranges 0.0-1.0 + double mFilteredBrake; // ranges 0.0-1.0 + double mFilteredSteering; // ranges -1.0-1.0 (left to right) + double mFilteredClutch; // ranges 0.0-1.0 + + // Misc + double mSteeringShaftTorque; // torque around steering shaft (used to be mSteeringArmForce, but that is not necessarily accurate for feedback purposes) + double mFront3rdDeflection; // deflection at front 3rd spring + double mRear3rdDeflection; // deflection at rear 3rd spring + + // Aerodynamics + double mFrontWingHeight; // front wing height + double mFrontRideHeight; // front ride height + double mRearRideHeight; // rear ride height + double mDrag; // drag + double mFrontDownforce; // front downforce + double mRearDownforce; // rear downforce + + // State/damage info + double mFuel; // amount of fuel (liters) + double mEngineMaxRPM; // rev limit + unsigned char mScheduledStops; // number of scheduled pitstops + bool mOverheating; // whether overheating icon is shown + bool mDetached; // whether any parts (besides wheels) have been detached + bool mHeadlights; // whether headlights are on + unsigned char mDentSeverity[8]; // dent severity at 8 locations around the car (0=none, 1=some, 2=more) + double mLastImpactET; // time of last impact + double mLastImpactMagnitude; // magnitude of last impact + TelemVect3 mLastImpactPos; // location of last impact + + // Expanded + double mEngineTorque; // current engine torque (including additive torque) (used to be mEngineTq, but there's little reason to abbreviate it) + long mCurrentSector; // the current sector (zero-based) with the pitlane stored in the sign bit (example: entering pits from third sector gives 0x80000002) + unsigned char mSpeedLimiter; // whether speed limiter is on + unsigned char mMaxGears; // maximum forward gears + unsigned char mFrontTireCompoundIndex; // index within brand + unsigned char mRearTireCompoundIndex; // index within brand + double mFuelCapacity; // capacity in liters + unsigned char mFrontFlapActivated; // whether front flap is activated + unsigned char mRearFlapActivated; // whether rear flap is activated + unsigned char mRearFlapLegalStatus; // 0=disallowed, 1=criteria detected but not allowed quite yet, 2=allowed + unsigned char mIgnitionStarter; // 0=off 1=ignition 2=ignition+starter + + char mFrontTireCompoundName[18]; // name of front tire compound + char mRearTireCompoundName[18]; // name of rear tire compound + + unsigned char mSpeedLimiterAvailable; // whether speed limiter is available + unsigned char mAntiStallActivated; // whether (hard) anti-stall is activated + unsigned char mUnused[2]; // + float mVisualSteeringWheelRange; // the *visual* steering wheel range + + double mRearBrakeBias; // fraction of brakes on rear + double mTurboBoostPressure; // current turbo boost pressure if available + float mPhysicsToGraphicsOffset[3]; // offset from static CG to graphical center + float mPhysicalSteeringWheelRange; // the *physical* steering wheel range + + // Future use + unsigned char mExpansion[152]; // 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 + TelemWheelV01 mWheel[4]; // wheel info (front left, front right, rear left, rear right) +}; + +struct GraphicsInfoV01 +{ + TelemVect3 mCamPos; // camera position + TelemVect3 mCamOri[3]; // rows of orientation matrix (use TelemQuat conversions if desired), also converts local + HWND mHWND; // app handle + + double mAmbientRed; + double mAmbientGreen; + double mAmbientBlue; +}; + +struct GraphicsInfoV02 : public GraphicsInfoV01 +{ + long mID; // slot ID being viewed (-1 if invalid) + + // Camera types (some of these may only be used for *setting* the camera type in WantsToViewVehicle()) + // 0 = TV cockpit + // 1 = cockpit + // 2 = nosecam + // 3 = swingman + // 4 = trackside (nearest) + // 5 = onboard000 + // : + // : + // 1004 = onboard999 + // 1005+ = (currently unsupported, in the future may be able to set/get specific trackside camera) + long mCameraType; // see above comments for possible values + + unsigned char mExpansion[128]; // for future use (possibly camera name) +}; + +struct CameraControlInfoV01 +{ + // Cameras + long mID; // slot ID to view + long mCameraType; // see GraphicsInfoV02 comments for values + + // Replays (note that these are asynchronous) + bool mReplayActive; // This variable is an *input* filled with whether the replay is currently active (as opposed to realtime). + bool mReplayUnused; // + unsigned char mReplayCommand; // 0=do nothing, 1=begin, 2=end, 3=rewind, 4=fast backwards, 5=backwards, 6=slow backwards, 7=stop, 8=slow play, 9=play, 10=fast play, 11=fast forward + + bool mReplaySetTime; // Whether to skip to the following replay time: + float mReplaySeconds; // The replay time in seconds to skip to (note: the current replay maximum ET is passed into this variable in case you need it) + + // + unsigned char mExpansion[120]; // for future use (possibly camera name & positions/orientations) +}; + +struct MessageInfoV01 +{ + char mText[128]; // message to display + + unsigned char mDestination; // 0 = message center, 1 = chat (can be used for multiplayer chat commands) + unsigned char mTranslate; // 0 = do not attempt to translate, 1 = attempt to translate + + unsigned char mExpansion[126]; // for future use (possibly what color, what font, and seconds to display) +}; + +struct VehicleScoringInfoV01 +{ + long mID; // slot ID (note that it can be re-used in multiplayer after someone leaves) + char mDriverName[32]; // driver name + char mVehicleName[64]; // vehicle name + short mTotalLaps; // laps completed + signed char mSector; // 0=sector3, 1=sector1, 2=sector2 (don't ask why) + signed char mFinishStatus; // 0=none, 1=finished, 2=dnf, 3=dq + double mLapDist; // current distance around track + double mPathLateral; // lateral position with respect to *very approximate* "center" path + double mTrackEdge; // track edge (w.r.t. "center" path) on same side of track as vehicle + + double mBestSector1; // best sector 1 + double mBestSector2; // best sector 2 (plus sector 1) + double mBestLapTime; // best lap time + double mLastSector1; // last sector 1 + double mLastSector2; // last sector 2 (plus sector 1) + double mLastLapTime; // last lap time + double mCurSector1; // current sector 1 if valid + double mCurSector2; // current sector 2 (plus sector 1) if valid + // no current laptime because it instantly becomes "last" + + short mNumPitstops; // number of pitstops made + short mNumPenalties; // number of outstanding penalties + bool mIsPlayer; // is this the player's vehicle + + signed char 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) + bool mInPits; // between pit entrance and pit exit (not always accurate for remote vehicles) + unsigned char mPlace; // 1-based position + char mVehicleClass[32]; // vehicle class + + // Dash Indicators + double mTimeBehindNext; // time behind vehicle in next higher place + long mLapsBehindNext; // laps behind vehicle in next higher place + double mTimeBehindLeader; // time behind leader + long mLapsBehindLeader; // laps behind leader + double mLapStartET; // time this lap was started + + // Position and derivatives + TelemVect3 mPos; // world position in meters + TelemVect3 mLocalVel; // velocity (meters/sec) in local vehicle coordinates + TelemVect3 mLocalAccel; // acceleration (meters/sec^2) in local vehicle coordinates + + // Orientation and derivatives + TelemVect3 mOri[3]; // 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 + TelemVect3 mLocalRot; // rotation (radians/sec) in local vehicle coordinates + TelemVect3 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 + unsigned char mHeadlights; // status of headlights + unsigned char mPitState; // 0=none, 1=request, 2=entering, 3=stopped, 4=exiting + unsigned char mServerScored; // whether this vehicle is being scored by server (could be off in qualifying or racing heats) + unsigned char mIndividualPhase; // game phases (described below) plus 9=after formation, 10=under yellow, 11=under blue (not used) + + long mQualification; // 1-based, can be -1 when invalid + + double mTimeIntoLap; // estimated time into lap + double mEstimatedLapTime; // estimated laptime used for 'time behind' and 'time into lap' (note: this may changed based on vehicle and setup!?) + + char mPitGroup[24]; // pit group (same as team name unless pit is shared) + unsigned char mFlag; // primary flag being shown to vehicle (currently only 0=green or 6=blue) + bool mUnderYellow; // whether this car has taken a full-course caution flag at the start/finish line + unsigned char mCountLapFlag; // 0 = do not count lap or time, 1 = count lap but not time, 2 = count lap and time + bool mInGarageStall; // appears to be within the correct garage stall + + unsigned char mUpgradePack[16]; // Coded upgrades + + // Future use + // tag.2012.04.06 - SEE ABOVE! + unsigned char mExpansion[60]; // for future use +}; + +struct ScoringInfoV01 +{ + char mTrackName[64]; // current track name + long mSession; // current session (0=testday 1-4=practice 5-8=qual 9=warmup 10-13=race) + double mCurrentET; // current time + double mEndET; // ending time + long mMaxLaps; // maximum laps + double mLapDist; // distance around track + char *mResultsStream; // results stream additions since last update (newline-delimited and NULL-terminated) + + long 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 + unsigned char 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) + signed char mYellowFlagState; + + signed char mSectorFlag[3]; // whether there are any local yellows at the moment in each sector (not sure if sector 0 is first or last, so test) + unsigned char mStartLight; // start light frame (number depends on track) + unsigned char mNumRedLights; // number of red lights in start sequence + bool mInRealtime; // in realtime as opposed to at the monitor + char mPlayerName[32]; // player name (including possible multiplayer override) + char mPlrFileName[64]; // may be encoded to be a legal filename + + // weather + double mDarkCloud; // cloud darkness? 0.0-1.0 + double mRaining; // raining severity 0.0-1.0 + double mAmbientTemp; // temperature (Celsius) + double mTrackTemp; // temperature (Celsius) + TelemVect3 mWind; // wind speed + double mMinPathWetness; // minimum wetness on main path 0.0-1.0 + double mMaxPathWetness; // maximum wetness on main path 0.0-1.0 + + // Future use + unsigned char mExpansion[256]; + + // 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 +}; + +struct CommentaryRequestInfoV01 +{ + char mName[32]; // one of the event names in the commentary INI file + double mInput1; // first value to pass in (if any) + double mInput2; // first value to pass in (if any) + double mInput3; // first value to pass in (if any) + bool mSkipChecks; // ignores commentary detail and random probability of event + + // constructor (for noobs, this just helps make sure everything is initialized to something reasonable) + CommentaryRequestInfoV01() + { + mName[0] = 0; + mInput1 = 0.0; + mInput2 = 0.0; + mInput3 = 0.0; + mSkipChecks = false; + } +}; + +//������������������������������������������������������������������������Ŀ +//� Version02 Structures � +//�������������������������������������������������������������������������� + +struct PhysicsOptionsV01 +{ + unsigned char mTractionControl; // 0 (off) - 3 (high) + unsigned char mAntiLockBrakes; // 0 (off) - 2 (high) + unsigned char mStabilityControl; // 0 (off) - 2 (high) + unsigned char mAutoShift; // 0 (off), 1 (upshifts), 2 (downshifts), 3 (all) + unsigned char mAutoClutch; // 0 (off), 1 (on) + unsigned char mInvulnerable; // 0 (off), 1 (on) + unsigned char mOppositeLock; // 0 (off), 1 (on) + unsigned char mSteeringHelp; // 0 (off) - 3 (high) + unsigned char mBrakingHelp; // 0 (off) - 2 (high) + unsigned char mSpinRecovery; // 0 (off), 1 (on) + unsigned char mAutoPit; // 0 (off), 1 (on) + unsigned char mAutoLift; // 0 (off), 1 (on) + unsigned char mAutoBlip; // 0 (off), 1 (on) + + unsigned char mFuelMult; // fuel multiplier (0x-7x) + unsigned char mTireMult; // tire wear multiplier (0x-7x) + unsigned char mMechFail; // mechanical failure setting; 0 (off), 1 (normal), 2 (timescaled) + unsigned char mAllowPitcrewPush; // 0 (off), 1 (on) + unsigned char mRepeatShifts; // accidental repeat shift prevention (0-5; see PLR file) + unsigned char mHoldClutch; // for auto-shifters at start of race: 0 (off), 1 (on) + unsigned char mAutoReverse; // 0 (off), 1 (on) + unsigned char 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) + unsigned char mAIControl; // Whether player vehicle is currently under AI control + unsigned char mUnused1; // + unsigned char mUnused2; // + + float mManualShiftOverrideTime; // time before auto-shifting can resume after recent manual shift + float mAutoShiftOverrideTime; // time before manual shifting can resume after recent auto shift + float mSpeedSensitiveSteering; // 0.0 (off) - 1.0 + float mSteerRatioSpeed; // speed (m/s) under which lock gets expanded to full +}; + +struct EnvironmentInfoV01 +{ + // TEMPORARY buffers (you should copy them if needed for later use) containing various paths that may be needed. Each of these + // could be relative ("UserData\") or full ("C:\BlahBlah\rFactorProduct\UserData\"). + // mPath[ 0 ] points to the UserData directory. + // mPath[ 1 ] points to the CustomPluginOptions.JSON filename. + // mPath[ 2 ] points to the latest results file + // (in the future, we may add paths for the current garage setup, fully upgraded physics files, etc., any other requests?) + const char *mPath[16]; + unsigned char mExpansion[256]; // future use +}; + +struct ScreenInfoV01 +{ + HWND mAppWindow; // Application window handle + void *mDevice; // Cast type to LPDIRECT3DDEVICE9 + void *mRenderTarget; // Cast type to LPDIRECT3DTEXTURE9 + long mDriver; // Current video driver index + + long mWidth; // Screen width + long mHeight; // Screen height + long mPixelFormat; // Pixel format + long mRefreshRate; // Refresh rate + long mWindowed; // Really just a boolean whether we are in windowed mode + + long mOptionsWidth; // Width dimension of screen portion used by UI + long mOptionsHeight; // Height dimension of screen portion used by UI + long mOptionsLeft; // Horizontal starting coordinate of screen portion used by UI + long mOptionsUpper; // Vertical starting coordinate of screen portion used by UI + + unsigned char mOptionsLocation; // 0=main UI, 1=track loading, 2=monitor, 3=on track + char mOptionsPage[31]; // the name of the options page + + unsigned char mExpansion[224]; // future use +}; + +struct CustomControlInfoV01 +{ + // The name passed through CheckHWControl() will be the mUntranslatedName prepended with an underscore (e.g. "Track Map Toggle" -> "_Track Map Toggle") + char mUntranslatedName[64]; // name of the control that will show up in UI (but translated if available) + long mRepeat; // 0=registers once per hit, 1=registers once, waits briefly, then starts repeating quickly, 2=registers as long as key is down + unsigned char mExpansion[64]; // future use +}; + +struct WeatherControlInfoV01 +{ + // The current conditions are passed in with the API call. The following ET (Elapsed Time) value should typically be far + // enough in the future that it can be interpolated smoothly, and allow clouds time to roll in before rain starts. In + // other words you probably shouldn't have mCloudiness and mRaining suddenly change from 0.0 to 1.0 and expect that + // to happen in a few seconds without looking crazy. + double mET; // when you want this weather to take effect + + // mRaining[1][1] is at the origin (2013.12.19 - and currently the only implemented node), while the others + // are spaced at meters where is the maximum absolute value of a track vertex + // coordinate (and is passed into the API call). + double mRaining[3][3]; // rain (0.0-1.0) at different nodes + + double mCloudiness; // general cloudiness (0.0=clear to 1.0=dark), will be automatically overridden to help ensure clouds exist over rainy areas + double mAmbientTempK; // ambient temperature (Kelvin) + double mWindMaxSpeed; // maximum speed of wind (ground speed, but it affects how fast the clouds move, too) + + bool mApplyCloudinessInstantly; // preferably we roll the new clouds in, but you can instantly change them now + bool mUnused1; // + bool mUnused2; // + bool mUnused3; // + + unsigned char mExpansion[508]; // future use (humidity, pressure, air density, etc.) +}; + +//������������������������������������������������������������������������Ŀ +//� Version07 Structures � +//�������������������������������������������������������������������������� + +struct CustomVariableV01 +{ + char mCaption[128]; // Name of variable. This will be used for storage. In the future, this may also be used in the UI (after attempting to translate). + long mNumSettings; // Number of available settings. The special value 0 should be used for types that have limitless possibilities, which will be treated as a string type. + long mCurrentSetting; // Current setting (also the default setting when returned in GetCustomVariable()). This is zero-based, so: ( 0 <= mCurrentSetting < mNumSettings ) + + // future expansion + unsigned char mExpansion[256]; +}; + +struct CustomSettingV01 +{ + char mName[128]; // Enumerated name of setting (only used if CustomVariableV01::mNumSettings > 0). This will be stored in the JSON file for informational purposes only. It may also possibly be used in the UI in the future. +}; + +struct MultiSessionParticipantV01 +{ + // input only + long mID; // slot ID (if loaded) or -1 (if currently disconnected) + char mDriverName[32]; // driver name + char mVehicleName[64]; // vehicle name + unsigned char mUpgradePack[16]; // coded upgrades + + float mBestPracticeTime; // best practice time + long mQualParticipantIndex; // once qualifying begins, this becomes valid and ranks participants according to practice time if possible + float mQualificationTime[4]; // best qualification time in up to 4 qual sessions + float mFinalRacePlace[4]; // final race place in up to 4 race sessions + float mFinalRaceTime[4]; // final race time in up to 4 race sessions + + // input/output + bool mServerScored; // whether vehicle is allowed to participate in current session + long mGridPosition; // 1-based grid position for current race session (or upcoming race session if it is currently warmup), or -1 if currently disconnected + // long mPitIndex; + // long mGarageIndex; + + // future expansion + unsigned char mExpansion[128]; +}; + +struct MultiSessionRulesV01 +{ + // input only + long mSession; // current session (0=testday 1-4=practice 5-8=qual 9=warmup 10-13=race) + long mSpecialSlotID; // slot ID of someone who just joined, or -2 requesting to update qual order, or -1 (default/general) + char mTrackType[32]; // track type from GDB + long mNumParticipants; // number of participants (vehicles) + + // input/output + MultiSessionParticipantV01 *mParticipant; // array of partipants (vehicles) + long mNumQualSessions; // number of qualifying sessions configured + long mNumRaceSessions; // number of race sessions configured + long mMaxLaps; // maximum laps allowed in current session (LONG_MAX = unlimited) (note: cannot currently edit in *race* sessions) + long mMaxSeconds; // maximum time allowed in current session (LONG_MAX = unlimited) (note: cannot currently edit in *race* sessions) + char mName[32]; // untranslated name override for session (please use mixed case here, it should get uppercased if necessary) + + // future expansion + unsigned char mExpansion[256]; +}; + +enum TrackRulesCommandV01 // +{ + TRCMD_ADD_FROM_TRACK = 0, // crossed s/f line for first time after full-course yellow was called + TRCMD_ADD_FROM_PIT, // exited pit during full-course yellow + TRCMD_ADD_FROM_UNDQ, // during a full-course yellow, the admin reversed a disqualification + TRCMD_REMOVE_TO_PIT, // entered pit during full-course yellow + TRCMD_REMOVE_TO_DNF, // vehicle DNF'd during full-course yellow + TRCMD_REMOVE_TO_DQ, // vehicle DQ'd during full-course yellow + TRCMD_REMOVE_TO_UNLOADED, // vehicle unloaded (possibly kicked out or banned) during full-course yellow + TRCMD_MOVE_TO_BACK, // misbehavior during full-course yellow, resulting in the penalty of being moved to the back of their current line + TRCMD_LONGEST_LINE, // misbehavior during full-course yellow, resulting in the penalty of being moved to the back of the longest line + //------------------ + TRCMD_MAXIMUM // should be last +}; + +struct TrackRulesActionV01 +{ + // input only + TrackRulesCommandV01 mCommand; // recommended action + long mID; // slot ID if applicable + double mET; // elapsed time that event occurred, if applicable +}; + +enum TrackRulesColumnV01 +{ + TRCOL_LEFT_LANE = 0, // left (inside) + TRCOL_MIDLEFT_LANE, // mid-left + TRCOL_MIDDLE_LANE, // middle + TRCOL_MIDRIGHT_LANE, // mid-right + TRCOL_RIGHT_LANE, // right (outside) + //------------------ + TRCOL_MAX_LANES, // should be after the valid static lane choices + //------------------ + TRCOL_INVALID = TRCOL_MAX_LANES, // currently invalid (hasn't crossed line or in pits/garage) + TRCOL_FREECHOICE, // free choice (dynamically chosen by driver) + TRCOL_PENDING, // depends on another participant's free choice (dynamically set after another driver chooses) + //------------------ + TRCOL_MAXIMUM // should be last +}; + +struct TrackRulesParticipantV01 +{ + // input only + long mID; // slot ID + short mFrozenOrder; // 0-based place when caution came out (not valid for formation laps) + short mPlace; // 1-based place (typically used for the initialization of the formation lap track order) + 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) + double mCurrentRelativeDistance; // equal to ( ( ScoringInfoV01::mLapDist * this->mRelativeLaps ) + VehicleScoringInfoV01::mLapDist ) + + // input/output + long 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') + TrackRulesColumnV01 mColumnAssignment; // which column (line/lane) that participant is supposed to be in + long mPositionAssignment; // 0-based position within column (line/lane) that participant is supposed to be located at (-1 is invalid) + bool mAllowedToPit; // whether the rules allow this particular vehicle to enter pits right now + bool mUnused[3]; // + double mGoalRelativeDistance; // calculated based on where the leader is, and adjusted by the desired column spacing and the column/position assignments + char mMessage[96]; // a message for this participant to explain what is going on (untranslated; it will get run through translator on client machines) + + // future expansion + unsigned char mExpansion[192]; +}; + +enum TrackRulesStageV01 // +{ + TRSTAGE_FORMATION_INIT = 0, // initialization of the formation lap + TRSTAGE_FORMATION_UPDATE, // update of the formation lap + TRSTAGE_NORMAL, // normal (non-yellow) update + TRSTAGE_CAUTION_INIT, // initialization of a full-course yellow + TRSTAGE_CAUTION_UPDATE, // update of a full-course yellow + //------------------ + TRSTAGE_MAXIMUM // should be last +}; + +struct TrackRulesV01 +{ + // input only + double mCurrentET; // current time + TrackRulesStageV01 mStage; // current stage + TrackRulesColumnV01 mPoleColumn; // column assignment where pole position seems to be located + long mNumActions; // number of recent actions + TrackRulesActionV01 *mAction; // array of recent actions + long mNumParticipants; // number of participants (vehicles) + + bool mYellowFlagDetected; // whether yellow flag was requested or sum of participant mYellowSeverity's exceeds mSafetyCarThreshold + bool mYellowFlagLapsWasOverridden; // whether mYellowFlagLaps (below) is an admin request + + bool mSafetyCarExists; // whether safety car even exists + bool mSafetyCarActive; // whether safety car is active + long mSafetyCarLaps; // number of laps + float mSafetyCarThreshold; // the threshold at which a safety car is called out (compared to the sum of TrackRulesParticipantV01::mYellowSeverity for each vehicle) + double mSafetyCarLapDist; // safety car lap distance + float mSafetyCarLapDistAtStart; // where the safety car starts from + + float mPitLaneStartDist; // where the waypoint branch to the pits breaks off (this may not be perfectly accurate) + float mTeleportLapDist; // the front of the teleport locations (a useful first guess as to where to throw the green flag) + + // future input expansion + unsigned char mInputExpansion[256]; + + // input/output + signed char mYellowFlagState; // see ScoringInfoV01 for values + short mYellowFlagLaps; // suggested number of laps to run under yellow (may be passed in with admin command) + + long mSafetyCarInstruction; // 0=no change, 1=go active, 2=head for pits + float mSafetyCarSpeed; // maximum speed at which to drive + float mSafetyCarMinimumSpacing; // minimum spacing behind safety car (-1 to indicate no limit) + float mSafetyCarMaximumSpacing; // maximum spacing behind safety car (-1 to indicate no limit) + + float mMinimumColumnSpacing; // minimum desired spacing between vehicles in a column (-1 to indicate indeterminate/unenforced) + float mMaximumColumnSpacing; // maximum desired spacing between vehicles in a column (-1 to indicate indeterminate/unenforced) + + float mMinimumSpeed; // minimum speed that anybody should be driving (-1 to indicate no limit) + float mMaximumSpeed; // maximum speed that anybody should be driving (-1 to indicate no limit) + + char mMessage[96]; // a message for everybody to explain what is going on (which will get run through translator on client machines) + TrackRulesParticipantV01 *mParticipant; // array of partipants (vehicles) + + // future input/output expansion + unsigned char mInputOutputExpansion[256]; +}; + +struct PitMenuV01 +{ + long mCategoryIndex; // index of the current category + char mCategoryName[32]; // name of the current category (untranslated) + + long mChoiceIndex; // index of the current choice (within the current category) + char mChoiceString[32]; // name of the current choice (may have some translated words) + long mNumChoices; // total number of choices (0 <= mChoiceIndex < mNumChoices) + + unsigned char mExpansion[256]; // for future use +}; + +//������������������������������������������������������������������������Ŀ +//� Plugin classes used to access internals � +//�������������������������������������������������������������������������� + +// Note: use class InternalsPluginV01 and have exported function GetPluginVersion() return 1, or +// use class InternalsPluginV02 and have exported function GetPluginVersion() return 2, etc. +class InternalsPlugin : public PluginObject +{ +public: + // General internals methods + InternalsPlugin() {} + virtual ~InternalsPlugin() {} + + // GAME FLOW NOTIFICATIONS + virtual void Startup(long version) {} // sim startup with version * 1000 + virtual void Shutdown() {} // sim shutdown + + virtual void Load() {} // scene/track load + virtual void Unload() {} // scene/track unload + + virtual void StartSession() {} // session started + virtual void EndSession() {} // session ended + + virtual void EnterRealtime() {} // entering realtime (where the vehicle can be driven) + virtual void ExitRealtime() {} // exiting realtime + + // SCORING OUTPUT + virtual bool WantsScoringUpdates() { return (false); } // whether we want scoring updates + virtual void UpdateScoring(const ScoringInfoV01 &info) {} // update plugin with scoring info (approximately five times per second) + + // GAME OUTPUT + virtual long WantsTelemetryUpdates() { return (0); } // whether we want telemetry updates (0=no 1=player-only 2=all vehicles) + virtual void UpdateTelemetry(const TelemInfoV01 &info) {} // update plugin with telemetry info + + virtual bool WantsGraphicsUpdates() { return (false); } // whether we want graphics updates + virtual void UpdateGraphics(const GraphicsInfoV01 &info) {} // update plugin with graphics info + + // COMMENTARY INPUT + virtual bool RequestCommentary(CommentaryRequestInfoV01 &info) { return (false); } // to use our commentary event system, fill in data and return true + + // GAME INPUT + virtual bool HasHardwareInputs() { return (false); } // whether plugin has hardware plugins + virtual void UpdateHardware(const double fDT) {} // update the hardware with the time between frames + virtual void EnableHardware() {} // message from game to enable hardware + virtual void DisableHardware() {} // message from game to disable hardware + + // See if the plugin wants to take over a hardware control. If the plugin takes over the + // control, this method returns true and sets the value of the double pointed to by the + // second arg. Otherwise, it returns false and leaves the double unmodified. + virtual bool CheckHWControl(const char *const controlName, double &fRetVal) { return false; } + + virtual bool ForceFeedback(double &forceValue) { return (false); } // alternate force feedback computation - return true if editing the value + + // ERROR FEEDBACK + virtual void Error(const char *const msg) {} // Called with explanation message if there was some sort of error in a plugin callback +}; + +class InternalsPluginV01 : public InternalsPlugin // Version 01 is the exact same as the original +{ + // REMINDER: exported function GetPluginVersion() should return 1 if you are deriving from this InternalsPluginV01! +}; + +class InternalsPluginV02 : public InternalsPluginV01 // V02 contains everything from V01 plus the following: +{ + // REMINDER: exported function GetPluginVersion() should return 2 if you are deriving from this InternalsPluginV02! + +public: + // This function is called occasionally + virtual void SetPhysicsOptions(PhysicsOptionsV01 &options) {} +}; + +class InternalsPluginV03 : public InternalsPluginV02 // V03 contains everything from V02 plus the following: +{ + // REMINDER: exported function GetPluginVersion() should return 3 if you are deriving from this InternalsPluginV03! + +public: + virtual unsigned char WantsToViewVehicle(CameraControlInfoV01 &camControl) { return (0); } // return values: 0=do nothing, 1=set ID and camera type, 2=replay controls, 3=both + + // EXTENDED GAME OUTPUT + virtual void UpdateGraphics(const GraphicsInfoV02 &info) {} // update plugin with extended graphics info + + // MESSAGE BOX INPUT + virtual bool WantsToDisplayMessage(MessageInfoV01 &msgInfo) { return (false); } // set message and return true +}; + +class InternalsPluginV04 : public InternalsPluginV03 // V04 contains everything from V03 plus the following: +{ + // REMINDER: exported function GetPluginVersion() should return 4 if you are deriving from this InternalsPluginV04! + +public: + // EXTENDED GAME FLOW NOTIFICATIONS + virtual void SetEnvironment(const EnvironmentInfoV01 &info) {} // may be called whenever the environment changes +}; + +class InternalsPluginV05 : public InternalsPluginV04 // V05 contains everything from V04 plus the following: +{ + // REMINDER: exported function GetPluginVersion() should return 5 if you are deriving from this InternalsPluginV05! + +public: + // SCREEN INFO NOTIFICATIONS + virtual void InitScreen(const ScreenInfoV01 &info) {} // Now happens right after graphics device initialization + virtual void UninitScreen(const ScreenInfoV01 &info) {} // Now happens right before graphics device uninitialization + + virtual void DeactivateScreen(const ScreenInfoV01 &info) {} // Window deactivation + virtual void ReactivateScreen(const ScreenInfoV01 &info) {} // Window reactivation + + virtual void RenderScreenBeforeOverlays(const ScreenInfoV01 &info) {} // before rFactor overlays + virtual void RenderScreenAfterOverlays(const ScreenInfoV01 &info) {} // after rFactor overlays + + virtual void PreReset(const ScreenInfoV01 &info) {} // after detecting device lost but before resetting + virtual void PostReset(const ScreenInfoV01 &info) {} // after resetting + + // CUSTOM CONTROLS + virtual bool InitCustomControl(CustomControlInfoV01 &info) { return (false); } // called repeatedly at startup until false is returned +}; + +class InternalsPluginV06 : public InternalsPluginV05 // V06 contains everything from V05 plus the following: +{ + // REMINDER: exported function GetPluginVersion() should return 6 if you are deriving from this InternalsPluginV06! + +public: + // CONDITIONS CONTROL + virtual bool WantsWeatherAccess() { return (false); } // change to true in order to read or write weather with AccessWeather() call: + virtual bool AccessWeather(double trackNodeSize, WeatherControlInfoV01 &info) { return (false); } // current weather is passed in; return true if you want to change it + + // ADDITIONAL GAMEFLOW NOTIFICATIONS + virtual void ThreadStarted(long type) {} // called just after a primary thread is started (type is 0=multimedia or 1=simulation) + virtual void ThreadStopping(long type) {} // called just before a primary thread is stopped (type is 0=multimedia or 1=simulation) +}; + +class InternalsPluginV07 : public InternalsPluginV06 // V07 contains everything from V06 plus the following: +{ + // REMINDER: exported function GetPluginVersion() should return 7 if you are deriving from this InternalsPluginV07! + +public: + // CUSTOM PLUGIN VARIABLES + // This relatively simple feature allows plugins to store settings in a shared location without doing their own + // file I/O. Direct UI support may also be added in the future so that end users can control plugin settings within + // rFactor. But for now, users can access the data in UserData\Player\CustomPluginOptions.JSON. + // Plugins should only access these variables through this interface, though: + virtual bool GetCustomVariable(long i, CustomVariableV01 &var) { return (false); } // At startup, this will be called with increasing index (starting at zero) until false is returned. Feel free to add/remove/rearrange the variables when updating your plugin; the index does not have to be consistent from run to run. + virtual void AccessCustomVariable(CustomVariableV01 &var) {} // This will be called at startup, shutdown, and any time that the variable is changed (within the UI). + virtual void GetCustomVariableSetting(CustomVariableV01 &var, long i, CustomSettingV01 &setting) {} // This gets the name of each possible setting for a given variable. + + // SCORING CONTROL (only available in single-player or on multiplayer server) + virtual bool WantsMultiSessionRulesAccess() { return (false); } // change to true in order to read or write multi-session rules + virtual bool AccessMultiSessionRules(MultiSessionRulesV01 &info) { return (false); } // current internal rules passed in; return true if you want to change them + + virtual bool WantsTrackRulesAccess() { return (false); } // change to true in order to read or write track order (during formation or caution laps) + virtual bool AccessTrackRules(TrackRulesV01 &info) { return (false); } // current track order passed in; return true if you want to change it (note: this will be called immediately after UpdateScoring() when appropriate) + + // PIT MENU INFO (currently, the only way to edit the pit menu is to use this in conjunction with CheckHWControl()) + virtual bool WantsPitMenuAccess() { return (false); } // change to true in order to view pit menu info + virtual bool AccessPitMenu(PitMenuV01 &info) { return (false); } // currently, the return code should always be false (because we may allow more direct editing in the future) +}; + +//������������������������������������������������������������������������Ŀ +//�������������������������������������������������������������������������� + +// See #pragma at top of file +#pragma pack(pop) + +#endif // _INTERNALS_PLUGIN_HPP_ diff --git a/Include/PluginObjects.hpp b/Include/PluginObjects.hpp new file mode 100644 index 0000000..80f7e2c --- /dev/null +++ b/Include/PluginObjects.hpp @@ -0,0 +1,82 @@ +//ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +//Ý Þ +//Ý Module: Header file for plugin object types Þ +//Ý Þ +//Ý Description: interface declarations for plugin objects Þ +//Ý Þ +//Ý This source code module, and all information, data, and algorithms Þ +//Ý associated with it, are part of isiMotor Technology (tm). Þ +//Ý PROPRIETARY AND CONFIDENTIAL Þ +//Ý Copyright (c) 1996-2013 Image Space Incorporated. All rights reserved. Þ +//Ý Þ +//Ý Change history: Þ +//Ý tag.2008.02.15: created Þ +//Ý Þ +//ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +#ifndef _PLUGIN_OBJECTS_HPP_ +#define _PLUGIN_OBJECTS_HPP_ + + +// rF currently uses 4-byte packing ... whatever the current packing is will +// be restored at the end of this include with another #pragma. +#pragma pack( push, 4 ) + + +//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +//³ types of plugins ³ +//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +enum PluginObjectType +{ + PO_INVALID = -1, + //------------------- + PO_GAMESTATS = 0, + PO_NCPLUGIN = 1, + PO_IVIBE = 2, + PO_INTERNALS = 3, + PO_RFONLINE = 4, + //------------------- + PO_MAXIMUM +}; + + +//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +//³ PluginObject ³ +//³ - interface used by plugin classes. ³ +//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +class PluginObject +{ + private: + + class PluginInfo *mInfo; // used by main executable to obtain info about the plugin that implements this object + + public: + + void SetInfo( class PluginInfo *p ) { mInfo = p; } // used by main executable + class PluginInfo *GetInfo() const { return( mInfo ); } // used by main executable + class PluginInfo *GetInfo() { return( mInfo ); } // used by main executable +}; + + +//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +//³ typedefs for dll functions - easier to use a typedef than to type ³ +//³ out the crazy syntax for declaring and casting function pointers ³ +//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +typedef const char * ( __cdecl *GETPLUGINNAME )(); +typedef PluginObjectType ( __cdecl *GETPLUGINTYPE )(); +typedef int ( __cdecl *GETPLUGINVERSION )(); +typedef PluginObject * ( __cdecl *CREATEPLUGINOBJECT )(); +typedef void ( __cdecl *DESTROYPLUGINOBJECT )( PluginObject *obj ); + + +//ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +//ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +// See #pragma at top of file +#pragma pack( pop ) + +#endif // _PLUGIN_OBJECTS_HPP_ + diff --git a/Include/RFServer.hpp b/Include/RFServer.hpp new file mode 100644 index 0000000..5df445a --- /dev/null +++ b/Include/RFServer.hpp @@ -0,0 +1,43 @@ + +#ifndef _RF_SERVER_H +#define _RF_SERVER_H + +#include "InternalsPlugin.hpp" +#include "Socket.hpp" + +// This is used for the app to use the plugin for its intended purpose +class RFServerPlugin : public InternalsPluginV07 // REMINDER: exported function GetPluginVersion() should return 1 if you are deriving from this InternalsPluginV01, 2 for InternalsPluginV02, etc. +{ + +public: + // Constructor/destructor + RFServerPlugin(); + ~RFServerPlugin(); + + // These are the functions derived from base class InternalsPlugin + // that can be implemented. + void Startup(long version); // game startup + void Shutdown(); // game shutdown + + void EnterRealtime(); // entering realtime + void ExitRealtime(); // exiting realtime + + void StartSession(); // session has started + void EndSession(); // session has ended + + // GAME OUTPUT + long WantsTelemetryUpdates() { return (1); } // CHANGE TO 1 TO ENABLE TELEMETRY EXAMPLE! + void UpdateTelemetry(const TelemInfoV01 &info); + + // SCORING OUTPUT + bool WantsScoringUpdates() { return (false); } // CHANGE TO TRUE TO ENABLE SCORING EXAMPLE! + void UpdateScoring(const ScoringInfoV01 &info); + + bool WantsPitMenuAccess() { return (true); } + bool AccessPitMenu(PitMenuV01 &info); + +private: + Socket *socket; +}; + +#endif // _RF_SERVER_H diff --git a/Include/Socket.hpp b/Include/Socket.hpp new file mode 100644 index 0000000..d08b213 --- /dev/null +++ b/Include/Socket.hpp @@ -0,0 +1,92 @@ +#ifndef _SOCKET_HPP_ +#define _SOCKET_HPP_ + +#include +#include +#include +#pragma comment(lib, "Ws2_32.lib") + +class Socket +{ +private: + SOCKET serverSocket; + struct sockaddr_in SenderAddr; + int SenderAddrSize; + +public: + Socket(short port) + { + int SenderAddrSize = sizeof(SenderAddr); + + WSADATA wsaData; + int res = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (res != NO_ERROR) + { + throw std::runtime_error("WSAStartup failed"); + } + + serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (serverSocket == INVALID_SOCKET) + { + throw std::runtime_error("socket creation failed: " + WSAGetLastError()); + } + + // Non blocking setting + u_long val = 1; // 0: blocking, 1: non-blocking + ioctlsocket(serverSocket, FIONBIO, &val); + + // Bind the socket to any address and the specified port. + struct sockaddr_in serverAddr; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(port); + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(serverSocket, (SOCKADDR *)&serverAddr, sizeof(serverAddr))) + { + throw std::runtime_error("binding socket failed: " + WSAGetLastError()); + } + } + + ~Socket() + { + closesocket(serverSocket); + WSACleanup(); + } + + std::string receive() + { + int bytes_received; + char serverBuf[1025]; + int serverBufLen = 1024; + + bytes_received = recvfrom(serverSocket, serverBuf, serverBufLen, 0 /* no flags*/, (SOCKADDR *)&SenderAddr, &SenderAddrSize); + if (bytes_received == SOCKET_ERROR) + { + throw std::runtime_error("receive failed: " + WSAGetLastError()); + } + + serverBuf[bytes_received] = '\0'; + + std::string msg(serverBuf); + + return msg; + } + + void send(std::string msg) + { + if (msg.length() > 1024) + { + throw std::runtime_error("msg is too long: " + msg.length()); + } + + int sendResult = sendto(serverSocket, (const char *)&msg, msg.length(), 0, (SOCKADDR *)&SenderAddr, SenderAddrSize); + if (sendResult == SOCKET_ERROR) + { + throw std::runtime_error("send failed: " + WSAGetLastError()); + } + } + +private: +}; + +#endif // _SOCKET_HPP_ \ No newline at end of file diff --git a/Source/Example.cpp b/Source/Example.cpp new file mode 100644 index 0000000..433e16b --- /dev/null +++ b/Source/Example.cpp @@ -0,0 +1,383 @@ +//ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ +//Ý Þ +//Ý Module: Internals Example Source File Þ +//Ý Þ +//Ý Description: Declarations for the Internals Example Plugin Þ +//Ý Þ +//Ý Þ +//Ý This source code module, and all information, data, and algorithms Þ +//Ý associated with it, are part of CUBE technology (tm). Þ +//Ý PROPRIETARY AND CONFIDENTIAL Þ +//Ý Copyright (c) 1996-2014 Image Space Incorporated. All rights reserved. Þ +//Ý Þ +//Ý Þ +//Ý Change history: Þ +//Ý tag.2005.11.30: created Þ +//Ý Þ +//ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß + +#include "Example.hpp" // corresponding header file +#include // for atan2, sqrt +#include // for sample output + + +// plugin information + +extern "C" __declspec( dllexport ) +const char * __cdecl GetPluginName() { return( "ExamplePlugin - 2008.02.13" ); } + +extern "C" __declspec( dllexport ) +PluginObjectType __cdecl GetPluginType() { return( PO_INTERNALS ); } + +extern "C" __declspec( dllexport ) +int __cdecl GetPluginVersion() { return( 1 ); } // InternalsPluginV01 functionality (if you change this return value, you must derive from the appropriate class!) + +extern "C" __declspec( dllexport ) +PluginObject * __cdecl CreatePluginObject() { return( (PluginObject *) new ExampleInternalsPlugin ); } + +extern "C" __declspec( dllexport ) +void __cdecl DestroyPluginObject( PluginObject *obj ) { delete( (ExampleInternalsPlugin *) obj ); } + + +// ExampleInternalsPlugin class + +void ExampleInternalsPlugin::WriteToAllExampleOutputFiles( const char * const openStr, const char * const msg ) +{ + FILE *fo; + + fo = fopen( "ExampleInternalsTelemetryOutput.txt", openStr ); + if( fo != NULL ) + { + fprintf( fo, "%s\n", msg ); + fclose( fo ); + } + + fo = fopen( "ExampleInternalsGraphicsOutput.txt", openStr ); + if( fo != NULL ) + { + fprintf( fo, "%s\n", msg ); + fclose( fo ); + } + + fo = fopen( "ExampleInternalsScoringOutput.txt", openStr ); + if( fo != NULL ) + { + fprintf( fo, "%s\n", msg ); + fclose( fo ); + } +} + + +void ExampleInternalsPlugin::Startup( long version ) +{ + char temp[80]; + sprintf( temp, "-STARTUP- (version %.3f)", (float) version / 1000.0f ); + + // Open ports, read configs, whatever you need to do. For now, I'll just clear out the + // example output data files. + WriteToAllExampleOutputFiles( "w", temp ); + + // default HW control enabled to true + mEnabled = true; +} + + +void ExampleInternalsPlugin::Shutdown() +{ + WriteToAllExampleOutputFiles( "a", "-SHUTDOWN-" ); +} + + +void ExampleInternalsPlugin::StartSession() +{ + WriteToAllExampleOutputFiles( "a", "--STARTSESSION--" ); +} + + +void ExampleInternalsPlugin::EndSession() +{ + WriteToAllExampleOutputFiles( "a", "--ENDSESSION--" ); +} + + +void ExampleInternalsPlugin::EnterRealtime() +{ + // start up timer every time we enter realtime + mET = 0.0; + WriteToAllExampleOutputFiles( "a", "---ENTERREALTIME---" ); +} + + +void ExampleInternalsPlugin::ExitRealtime() +{ + WriteToAllExampleOutputFiles( "a", "---EXITREALTIME---" ); +} + + +void ExampleInternalsPlugin::UpdateTelemetry( const TelemInfoV01 &info ) +{ + // Use the incoming data, for now I'll just write some of it to a file to a) make sure it + // is working, and b) explain the coordinate system a little bit (see header for more info) + FILE *fo = fopen( "ExampleInternalsTelemetryOutput.txt", "a" ); + if( fo != NULL ) + { + // Delta time is variable, as we send out the info once per frame + fprintf( fo, "DT=%.4f ET=%.4f\n", info.mDeltaTime, info.mElapsedTime ); + fprintf( fo, "Lap=%d StartET=%.3f\n", info.mLapNumber, info.mLapStartET ); + fprintf( fo, "Vehicle=%s\n", info.mVehicleName ); + fprintf( fo, "Track=%s\n", info.mTrackName ); + fprintf( fo, "Pos=(%.3f,%.3f,%.3f)\n", info.mPos.x, info.mPos.y, info.mPos.z ); + + // Forward is roughly in the -z direction (although current pitch of car may cause some y-direction velocity) + fprintf( fo, "LocalVel=(%.2f,%.2f,%.2f)\n", info.mLocalVel.x, info.mLocalVel.y, info.mLocalVel.z ); + fprintf( fo, "LocalAccel=(%.1f,%.1f,%.1f)\n", info.mLocalAccel.x, info.mLocalAccel.y, info.mLocalAccel.z ); + + // Orientation matrix is left-handed + fprintf( fo, "[%6.3f,%6.3f,%6.3f]\n", info.mOri[0].x, info.mOri[0].y, info.mOri[0].z ); + fprintf( fo, "[%6.3f,%6.3f,%6.3f]\n", info.mOri[1].x, info.mOri[1].y, info.mOri[1].z ); + fprintf( fo, "[%6.3f,%6.3f,%6.3f]\n", info.mOri[2].x, info.mOri[2].y, info.mOri[2].z ); + fprintf( fo, "LocalRot=(%.3f,%.3f,%.3f)\n", info.mLocalRot.x, info.mLocalRot.y, info.mLocalRot.z ); + fprintf( fo, "LocalRotAccel=(%.2f,%.2f,%.2f)\n", info.mLocalRotAccel.x, info.mLocalRotAccel.y, info.mLocalRotAccel.z ); + + // Vehicle status + fprintf( fo, "Gear=%d RPM=%.1f RevLimit=%.1f\n", info.mGear, info.mEngineRPM, info.mEngineMaxRPM ); + fprintf( fo, "Water=%.1f Oil=%.1f\n", info.mEngineWaterTemp, info.mEngineOilTemp ); + fprintf( fo, "ClutchRPM=%.1f\n", info.mClutchRPM ); + + // Driver input + fprintf( fo, "UnfilteredThrottle=%.1f%%\n", 100.0 * info.mUnfilteredThrottle ); + fprintf( fo, "UnfilteredBrake=%.1f%%\n", 100.0 * info.mUnfilteredBrake ); + fprintf( fo, "UnfilteredSteering=%.1f%%\n", 100.0 * info.mUnfilteredSteering ); + fprintf( fo, "UnfilteredClutch=%.1f%%\n", 100.0 * info.mUnfilteredClutch ); + + // Filtered input + fprintf( fo, "FilteredThrottle=%.1f%%\n", 100.0 * info.mFilteredThrottle ); + fprintf( fo, "FilteredBrake=%.1f%%\n", 100.0 * info.mFilteredBrake ); + fprintf( fo, "FilteredSteering=%.1f%%\n", 100.0 * info.mFilteredSteering ); + fprintf( fo, "FilteredClutch=%.1f%%\n", 100.0 * info.mFilteredClutch ); + + // Misc + fprintf( fo, "SteeringShaftTorque=%.1f\n", info.mSteeringShaftTorque ); + fprintf( fo, "Front3rdDeflection=%.3f Rear3rdDeflection=%.3f\n", info.mFront3rdDeflection, info.mRear3rdDeflection ); + + // Aerodynamics + fprintf( fo, "FrontWingHeight=%.3f FrontRideHeight=%.3f RearRideHeight=%.3f\n", info.mFrontWingHeight, info.mFrontRideHeight, info.mRearRideHeight ); + fprintf( fo, "Drag=%.1f FrontDownforce=%.1f RearDownforce=%.1f\n", info.mDrag, info.mFrontDownforce, info.mRearDownforce ); + + // Other + fprintf( fo, "Fuel=%.1f ScheduledStops=%d Overheating=%d Detached=%d\n", info.mFuel, info.mScheduledStops, info.mOverheating, info.mDetached ); + fprintf( fo, "Dents=(%d,%d,%d,%d,%d,%d,%d,%d)\n", info.mDentSeverity[0], info.mDentSeverity[1], info.mDentSeverity[2], info.mDentSeverity[3], + info.mDentSeverity[4], info.mDentSeverity[5], info.mDentSeverity[6], info.mDentSeverity[7] ); + fprintf( fo, "LastImpactET=%.1f Mag=%.1f, Pos=(%.1f,%.1f,%.1f)\n", info.mLastImpactET, info.mLastImpactMagnitude, + info.mLastImpactPos.x, info.mLastImpactPos.y, info.mLastImpactPos.z ); + + // Wheels + for( long i = 0; i < 4; ++i ) + { + const TelemWheelV01 &wheel = info.mWheel[i]; + fprintf( fo, "Wheel=%s\n", (i==0)?"FrontLeft":(i==1)?"FrontRight":(i==2)?"RearLeft":"RearRight" ); + fprintf( fo, " SuspensionDeflection=%.3f RideHeight=%.3f\n", wheel.mSuspensionDeflection, wheel.mRideHeight ); + fprintf( fo, " SuspForce=%.1f BrakeTemp=%.1f BrakePressure=%.3f\n", wheel.mSuspForce, wheel.mBrakeTemp, wheel.mBrakePressure ); + fprintf( fo, " ForwardRotation=%.1f Camber=%.3f\n", -wheel.mRotation, wheel.mCamber ); + fprintf( fo, " LateralPatchVel=%.2f LongitudinalPatchVel=%.2f\n", wheel.mLateralPatchVel, wheel.mLongitudinalPatchVel ); + fprintf( fo, " LateralGroundVel=%.2f LongitudinalGroundVel=%.2f\n", wheel.mLateralGroundVel, wheel.mLongitudinalGroundVel ); + fprintf( fo, " LateralForce=%.1f LongitudinalForce=%.1f\n", wheel.mLateralForce, wheel.mLongitudinalForce ); + fprintf( fo, " TireLoad=%.1f GripFract=%.3f TirePressure=%.1f\n", wheel.mTireLoad, wheel.mGripFract, wheel.mPressure ); + fprintf( fo, " TireTemp(l/c/r)=%.1f/%.1f/%.1f\n", wheel.mTemperature[0], wheel.mTemperature[1], wheel.mTemperature[2] ); + fprintf( fo, " Wear=%.3f TerrainName=%s SurfaceType=%d\n", wheel.mWear, wheel.mTerrainName, wheel.mSurfaceType ); + fprintf( fo, " Flat=%d Detached=%d\n", wheel.mFlat, wheel.mDetached ); + } + + // Compute some auxiliary info based on the above + TelemVect3 forwardVector = { -info.mOri[0].z, -info.mOri[1].z, -info.mOri[2].z }; + TelemVect3 leftVector = { info.mOri[0].x, info.mOri[1].x, info.mOri[2].x }; + + // These are normalized vectors, and remember that our world Y coordinate is up. So you can + // determine the current pitch and roll (w.r.t. the world x-z plane) as follows: + const double pitch = atan2( forwardVector.y, sqrt( ( forwardVector.x * forwardVector.x ) + ( forwardVector.z * forwardVector.z ) ) ); + const double roll = atan2( leftVector.y, sqrt( ( leftVector.x * leftVector.x ) + ( leftVector.z * leftVector.z ) ) ); + const double radsToDeg = 57.296; + fprintf( fo, "Pitch = %.1f deg, Roll = %.1f deg\n", pitch * radsToDeg, roll * radsToDeg ); + + const double metersPerSec = sqrt( ( info.mLocalVel.x * info.mLocalVel.x ) + + ( info.mLocalVel.y * info.mLocalVel.y ) + + ( info.mLocalVel.z * info.mLocalVel.z ) ); + fprintf( fo, "Speed = %.1f KPH, %.1f MPH\n\n", metersPerSec * 3.6, metersPerSec * 2.237 ); + + // Close file + fclose( fo ); + } +} + + +void ExampleInternalsPlugin::UpdateGraphics( const GraphicsInfoV01 &info ) +{ + // Use the incoming data, for now I'll just write some of it to a file to a) make sure it + // is working, and b) explain the coordinate system a little bit (see header for more info) + FILE *fo = fopen( "ExampleInternalsGraphicsOutput.txt", "a" ); + if( fo != NULL ) + { + // Print stuff + fprintf( fo, "CamPos=(%.1f,%.1f,%.1f)\n", info.mCamPos.x, info.mCamPos.y, info.mCamPos.z ); + fprintf( fo, "CamOri[0]=(%.1f,%.1f,%.1f)\n", info.mCamOri[0].x, info.mCamOri[0].y, info.mCamOri[0].z ); + fprintf( fo, "CamOri[1]=(%.1f,%.1f,%.1f)\n", info.mCamOri[1].x, info.mCamOri[1].y, info.mCamOri[1].z ); + fprintf( fo, "CamOri[2]=(%.1f,%.1f,%.1f)\n", info.mCamOri[2].x, info.mCamOri[2].y, info.mCamOri[2].z ); + fprintf( fo, "HWND=%d\n", info.mHWND ); + fprintf( fo, "Ambient Color=(%.1f,%.1f,%.1f)\n\n", info.mAmbientRed, info.mAmbientGreen, info.mAmbientBlue ); + + // Close file + fclose( fo ); + } +} + + +bool ExampleInternalsPlugin::CheckHWControl( const char * const controlName, double &fRetVal ) +{ + // only if enabled, of course + if( !mEnabled ) + return( false ); + + // Note that incoming value is the game's computation, in case you're interested. + + // Sorry, no control allowed over actual vehicle inputs ... would be too easy to cheat! + // However, you can still look at the values. + + // Note: since the game calls this function every frame for every available control, you might consider + // doing a binary search if you are checking more than 7 or 8 strings, just to keep the speed up. + if( _stricmp( controlName, "LookLeft" ) == 0 ) + { + const double headSwitcheroo = fmod( mET, 2.0 ); + if( headSwitcheroo < 0.5 ) + fRetVal = 1.0; + else + fRetVal = 0.0; + return( true ); + } + else if( _stricmp( controlName, "LookRight" ) == 0 ) + { + const double headSwitcheroo = fmod( mET, 2.0 ); + if( ( headSwitcheroo > 1.0 ) && ( headSwitcheroo < 1.5 ) ) + fRetVal = 1.0; + else + fRetVal = 0.0; + return( true ); + } + + return( false ); +} + + +bool ExampleInternalsPlugin::ForceFeedback( double &forceValue ) +{ + // Note that incoming value is the game's computation, in case you're interested. +#if 0 // enable to log it out (note that this is a very very slow implementation) + FILE *fo = fopen( "FFB.txt", "a" ); + if( fo != NULL ) + { + fprintf( fo, "\nFFB=%.4f", forceValue ); + fclose( fo ); + } +#endif + + // CHANGE COMMENTS TO ENABLE FORCE EXAMPLE + return( false ); + + // I think the bounds are -11500 to 11500 ... +// forceValue = 11500.0 * sinf( mET ); +// return( true ); +} + + +void ExampleInternalsPlugin::UpdateScoring( const ScoringInfoV01 &info ) +{ + // Note: function is called twice per second now (instead of once per second in previous versions) + FILE *fo = fopen( "ExampleInternalsScoringOutput.txt", "a" ); + if( fo != NULL ) + { + // Print general scoring info + fprintf( fo, "TrackName=%s\n", info.mTrackName ); + fprintf( fo, "Session=%d NumVehicles=%d CurET=%.3f\n", info.mSession, info.mNumVehicles, info.mCurrentET ); + fprintf( fo, "EndET=%.3f MaxLaps=%d LapDist=%.1f\n", info.mEndET, info.mMaxLaps, info.mLapDist ); + + // Note that only one plugin can use the stream (by enabling scoring updates) ... sorry if any clashes result + fprintf( fo, "START STREAM\n" ); + const char *ptr = info.mResultsStream; + while( *ptr != NULL ) + fputc( *ptr++, fo ); + fprintf( fo, "END STREAM\n" ); + + // New version 2 stuff + fprintf( fo, "GamePhase=%d YellowFlagState=%d SectorFlags=(%d,%d,%d)\n", info.mGamePhase, info.mYellowFlagState, + info.mSectorFlag[0], info.mSectorFlag[1], info.mSectorFlag[2] ); + fprintf( fo, "InRealtime=%d StartLight=%d NumRedLights=%d\n", info.mInRealtime, info.mStartLight, info.mNumRedLights ); + fprintf( fo, "PlayerName=%s PlrFileName=%s\n", info.mPlayerName, info.mPlrFileName ); + fprintf( fo, "DarkCloud=%.2f Raining=%.2f AmbientTemp=%.1f TrackTemp=%.1f\n", info.mDarkCloud, info.mRaining, info.mAmbientTemp, info.mTrackTemp ); + fprintf( fo, "Wind=(%.1f,%.1f,%.1f) MinPathWetness=%.2f MaxPathWetness=%.2f\n", info.mWind.x, info.mWind.y, info.mWind.z, info.mMinPathWetness, info.mMaxPathWetness ); + + // Print vehicle info + for( long i = 0; i < info.mNumVehicles; ++i ) + { + VehicleScoringInfoV01 &vinfo = info.mVehicle[ i ]; + fprintf( fo, "Driver %d: %s\n", i, vinfo.mDriverName ); + fprintf( fo, " ID=%d Vehicle=%s\n", vinfo.mID, vinfo.mVehicleName ); + fprintf( fo, " Laps=%d Sector=%d FinishStatus=%d\n", vinfo.mTotalLaps, vinfo.mSector, vinfo.mFinishStatus ); + fprintf( fo, " LapDist=%.1f PathLat=%.2f RelevantTrackEdge=%.2f\n", vinfo.mLapDist, vinfo.mPathLateral, vinfo.mTrackEdge ); + fprintf( fo, " Best=(%.3f, %.3f, %.3f)\n", vinfo.mBestSector1, vinfo.mBestSector2, vinfo.mBestLapTime ); + fprintf( fo, " Last=(%.3f, %.3f, %.3f)\n", vinfo.mLastSector1, vinfo.mLastSector2, vinfo.mLastLapTime ); + fprintf( fo, " Current Sector 1 = %.3f, Current Sector 2 = %.3f\n", vinfo.mCurSector1, vinfo.mCurSector2 ); + fprintf( fo, " Pitstops=%d, Penalties=%d\n", vinfo.mNumPitstops, vinfo.mNumPenalties ); + + // New version 2 stuff + fprintf( fo, " IsPlayer=%d Control=%d InPits=%d LapStartET=%.3f\n", vinfo.mIsPlayer, vinfo.mControl, vinfo.mInPits, vinfo.mLapStartET ); + fprintf( fo, " Place=%d VehicleClass=%s\n", vinfo.mPlace, vinfo.mVehicleClass ); + fprintf( fo, " TimeBehindNext=%.3f LapsBehindNext=%d\n", vinfo.mTimeBehindNext, vinfo.mLapsBehindNext ); + fprintf( fo, " TimeBehindLeader=%.3f LapsBehindLeader=%d\n", vinfo.mTimeBehindLeader, vinfo.mLapsBehindLeader ); + fprintf( fo, " Pos=(%.3f,%.3f,%.3f)\n", vinfo.mPos.x, vinfo.mPos.y, vinfo.mPos.z ); + + // Forward is roughly in the -z direction (although current pitch of car may cause some y-direction velocity) + fprintf( fo, " LocalVel=(%.2f,%.2f,%.2f)\n", vinfo.mLocalVel.x, vinfo.mLocalVel.y, vinfo.mLocalVel.z ); + fprintf( fo, " LocalAccel=(%.1f,%.1f,%.1f)\n", vinfo.mLocalAccel.x, vinfo.mLocalAccel.y, vinfo.mLocalAccel.z ); + + // Orientation matrix is left-handed + fprintf( fo, " [%6.3f,%6.3f,%6.3f]\n", vinfo.mOri[0].x, vinfo.mOri[0].y, vinfo.mOri[0].z ); + fprintf( fo, " [%6.3f,%6.3f,%6.3f]\n", vinfo.mOri[1].x, vinfo.mOri[1].y, vinfo.mOri[1].z ); + fprintf( fo, " [%6.3f,%6.3f,%6.3f]\n", vinfo.mOri[2].x, vinfo.mOri[2].y, vinfo.mOri[2].z ); + fprintf( fo, " LocalRot=(%.3f,%.3f,%.3f)\n", vinfo.mLocalRot.x, vinfo.mLocalRot.y, vinfo.mLocalRot.z ); + fprintf( fo, " LocalRotAccel=(%.2f,%.2f,%.2f)\n", vinfo.mLocalRotAccel.x, vinfo.mLocalRotAccel.y, vinfo.mLocalRotAccel.z ); + } + + // Delimit sections + fprintf( fo, "\n" ); + + // Close file + fclose( fo ); + } +} + + +bool ExampleInternalsPlugin::RequestCommentary( CommentaryRequestInfoV01 &info ) +{ + // COMMENT OUT TO ENABLE EXAMPLE + return( false ); + + // only if enabled, of course + if( !mEnabled ) + return( false ); + + // Note: function is called twice per second + + // Say green flag event for no particular reason every 20 seconds ... + const double timeMod20 = fmod( mET, 20.0 ); + if( timeMod20 > 19.0 ) + { + strcpy( info.mName, "GreenFlag" ); + info.mInput1 = 0.0; + info.mInput2 = 0.0; + info.mInput3 = 0.0; + info.mSkipChecks = true; + return( true ); + } + + return( false ); +} + diff --git a/Source/RFServer.cpp b/Source/RFServer.cpp new file mode 100644 index 0000000..68ac2d3 --- /dev/null +++ b/Source/RFServer.cpp @@ -0,0 +1,238 @@ +#include "RFServer.hpp" // corresponding header file +#include // for atan2, sqrt +#include // for sample output +#include + +// plugin information + +extern "C" __declspec(dllexport) + const char *__cdecl GetPluginName() { return ("rF Server Plugin"); } + +extern "C" __declspec(dllexport) + PluginObjectType __cdecl GetPluginType() { return (PO_INTERNALS); } + +extern "C" __declspec(dllexport) int __cdecl GetPluginVersion() { return (7); } // InternalsPluginV07 functionality + +extern "C" __declspec(dllexport) + PluginObject *__cdecl CreatePluginObject() { return ((PluginObject *)new RFServerPlugin); } + +extern "C" __declspec(dllexport) void __cdecl DestroyPluginObject(PluginObject *obj) { delete ((RFServerPlugin *)obj); } + +// RFServerPlugin class + +RFServerPlugin::RFServerPlugin() +{ + socket = new Socket(6262); +} + +RFServerPlugin::~RFServerPlugin() +{ + delete socket; +} + +void RFServerPlugin::Startup(long version) +{ +} + +void RFServerPlugin::Shutdown() +{ +} + +void RFServerPlugin::StartSession() +{ +} + +void RFServerPlugin::EndSession() +{ +} + +void RFServerPlugin::EnterRealtime() +{ +} + +void RFServerPlugin::ExitRealtime() +{ +} + +void RFServerPlugin::UpdateTelemetry(const TelemInfoV01 &info) +{ + // Use the incoming data, for now I'll just write some of it to a file to a) make sure it + // is working, and b) explain the coordinate system a little bit (see header for more info) + FILE *fo = fopen("ExampleInternalsTelemetryOutput.txt", "a"); + if (fo != NULL) + { + // Delta time is variable, as we send out the info once per frame + fprintf(fo, "DT=%.4f ET=%.4f\n", info.mDeltaTime, info.mElapsedTime); + fprintf(fo, "Lap=%d StartET=%.3f\n", info.mLapNumber, info.mLapStartET); + fprintf(fo, "Vehicle=%s\n", info.mVehicleName); + fprintf(fo, "Track=%s\n", info.mTrackName); + fprintf(fo, "Pos=(%.3f,%.3f,%.3f)\n", info.mPos.x, info.mPos.y, info.mPos.z); + + // Forward is roughly in the -z direction (although current pitch of car may cause some y-direction velocity) + fprintf(fo, "LocalVel=(%.2f,%.2f,%.2f)\n", info.mLocalVel.x, info.mLocalVel.y, info.mLocalVel.z); + fprintf(fo, "LocalAccel=(%.1f,%.1f,%.1f)\n", info.mLocalAccel.x, info.mLocalAccel.y, info.mLocalAccel.z); + + // Orientation matrix is left-handed + fprintf(fo, "[%6.3f,%6.3f,%6.3f]\n", info.mOri[0].x, info.mOri[0].y, info.mOri[0].z); + fprintf(fo, "[%6.3f,%6.3f,%6.3f]\n", info.mOri[1].x, info.mOri[1].y, info.mOri[1].z); + fprintf(fo, "[%6.3f,%6.3f,%6.3f]\n", info.mOri[2].x, info.mOri[2].y, info.mOri[2].z); + fprintf(fo, "LocalRot=(%.3f,%.3f,%.3f)\n", info.mLocalRot.x, info.mLocalRot.y, info.mLocalRot.z); + fprintf(fo, "LocalRotAccel=(%.2f,%.2f,%.2f)\n", info.mLocalRotAccel.x, info.mLocalRotAccel.y, info.mLocalRotAccel.z); + + // Vehicle status + fprintf(fo, "Gear=%d RPM=%.1f RevLimit=%.1f\n", info.mGear, info.mEngineRPM, info.mEngineMaxRPM); + fprintf(fo, "Water=%.1f Oil=%.1f\n", info.mEngineWaterTemp, info.mEngineOilTemp); + fprintf(fo, "ClutchRPM=%.1f\n", info.mClutchRPM); + + // Driver input + fprintf(fo, "UnfilteredThrottle=%.1f%%\n", 100.0 * info.mUnfilteredThrottle); + fprintf(fo, "UnfilteredBrake=%.1f%%\n", 100.0 * info.mUnfilteredBrake); + fprintf(fo, "UnfilteredSteering=%.1f%%\n", 100.0 * info.mUnfilteredSteering); + fprintf(fo, "UnfilteredClutch=%.1f%%\n", 100.0 * info.mUnfilteredClutch); + + // Filtered input + fprintf(fo, "FilteredThrottle=%.1f%%\n", 100.0 * info.mFilteredThrottle); + fprintf(fo, "FilteredBrake=%.1f%%\n", 100.0 * info.mFilteredBrake); + fprintf(fo, "FilteredSteering=%.1f%%\n", 100.0 * info.mFilteredSteering); + fprintf(fo, "FilteredClutch=%.1f%%\n", 100.0 * info.mFilteredClutch); + + // Misc + fprintf(fo, "SteeringShaftTorque=%.1f\n", info.mSteeringShaftTorque); + fprintf(fo, "Front3rdDeflection=%.3f Rear3rdDeflection=%.3f\n", info.mFront3rdDeflection, info.mRear3rdDeflection); + + // Aerodynamics + fprintf(fo, "FrontWingHeight=%.3f FrontRideHeight=%.3f RearRideHeight=%.3f\n", info.mFrontWingHeight, info.mFrontRideHeight, info.mRearRideHeight); + fprintf(fo, "Drag=%.1f FrontDownforce=%.1f RearDownforce=%.1f\n", info.mDrag, info.mFrontDownforce, info.mRearDownforce); + + // Other + fprintf(fo, "Fuel=%.1f ScheduledStops=%d Overheating=%d Detached=%d\n", info.mFuel, info.mScheduledStops, info.mOverheating, info.mDetached); + fprintf(fo, "Dents=(%d,%d,%d,%d,%d,%d,%d,%d)\n", info.mDentSeverity[0], info.mDentSeverity[1], info.mDentSeverity[2], info.mDentSeverity[3], + info.mDentSeverity[4], info.mDentSeverity[5], info.mDentSeverity[6], info.mDentSeverity[7]); + fprintf(fo, "LastImpactET=%.1f Mag=%.1f, Pos=(%.1f,%.1f,%.1f)\n", info.mLastImpactET, info.mLastImpactMagnitude, + info.mLastImpactPos.x, info.mLastImpactPos.y, info.mLastImpactPos.z); + + // Wheels + for (long i = 0; i < 4; ++i) + { + const TelemWheelV01 &wheel = info.mWheel[i]; + fprintf(fo, "Wheel=%s\n", (i == 0) ? "FrontLeft" : (i == 1) ? "FrontRight" + : (i == 2) ? "RearLeft" + : "RearRight"); + fprintf(fo, " SuspensionDeflection=%.3f RideHeight=%.3f\n", wheel.mSuspensionDeflection, wheel.mRideHeight); + fprintf(fo, " SuspForce=%.1f BrakeTemp=%.1f BrakePressure=%.3f\n", wheel.mSuspForce, wheel.mBrakeTemp, wheel.mBrakePressure); + fprintf(fo, " ForwardRotation=%.1f Camber=%.3f\n", -wheel.mRotation, wheel.mCamber); + fprintf(fo, " LateralPatchVel=%.2f LongitudinalPatchVel=%.2f\n", wheel.mLateralPatchVel, wheel.mLongitudinalPatchVel); + fprintf(fo, " LateralGroundVel=%.2f LongitudinalGroundVel=%.2f\n", wheel.mLateralGroundVel, wheel.mLongitudinalGroundVel); + fprintf(fo, " LateralForce=%.1f LongitudinalForce=%.1f\n", wheel.mLateralForce, wheel.mLongitudinalForce); + fprintf(fo, " TireLoad=%.1f GripFract=%.3f TirePressure=%.1f\n", wheel.mTireLoad, wheel.mGripFract, wheel.mPressure); + fprintf(fo, " TireTemp(l/c/r)=%.1f/%.1f/%.1f\n", wheel.mTemperature[0], wheel.mTemperature[1], wheel.mTemperature[2]); + fprintf(fo, " Wear=%.3f TerrainName=%s SurfaceType=%d\n", wheel.mWear, wheel.mTerrainName, wheel.mSurfaceType); + fprintf(fo, " Flat=%d Detached=%d\n", wheel.mFlat, wheel.mDetached); + } + + // Compute some auxiliary info based on the above + TelemVect3 forwardVector = {-info.mOri[0].z, -info.mOri[1].z, -info.mOri[2].z}; + TelemVect3 leftVector = {info.mOri[0].x, info.mOri[1].x, info.mOri[2].x}; + + // These are normalized vectors, and remember that our world Y coordinate is up. So you can + // determine the current pitch and roll (w.r.t. the world x-z plane) as follows: + const double pitch = atan2(forwardVector.y, sqrt((forwardVector.x * forwardVector.x) + (forwardVector.z * forwardVector.z))); + const double roll = atan2(leftVector.y, sqrt((leftVector.x * leftVector.x) + (leftVector.z * leftVector.z))); + const double radsToDeg = 57.296; + fprintf(fo, "Pitch = %.1f deg, Roll = %.1f deg\n", pitch * radsToDeg, roll * radsToDeg); + + const double metersPerSec = sqrt((info.mLocalVel.x * info.mLocalVel.x) + + (info.mLocalVel.y * info.mLocalVel.y) + + (info.mLocalVel.z * info.mLocalVel.z)); + fprintf(fo, "Speed = %.1f KPH, %.1f MPH\n\n", metersPerSec * 3.6, metersPerSec * 2.237); + + // Close file + fclose(fo); + } +} + +std::string format_float(double d, int precision) +{ + std::stringstream sstream; + + sstream << d; + sstream.precision(precision); + + return sstream.str(); +} + +void RFServerPlugin::UpdateScoring(const ScoringInfoV01 &info) +{ + std::string msg = "["; + msg += info.mMaxLaps + ";"; + msg += format_float(info.mLapDist, 1) + ";"; + msg += + + // Note: function is called twice per second now (instead of once per second in previous versions) + FILE *fo = fopen("ExampleInternalsScoringOutput.txt", "a"); + if (fo != NULL) + { + // Print general scoring info + fprintf(fo, "TrackName=%s\n", info.mTrackName); + fprintf(fo, "Session=%d NumVehicles=%d CurET=%.3f\n", info.mSession, info.mNumVehicles, info.mCurrentET); + fprintf(fo, "EndET=%.3f MaxLaps=%d LapDist=%.1f\n", info.mEndET, info.mMaxLaps, info.mLapDist); + + // Note that only one plugin can use the stream (by enabling scoring updates) ... sorry if any clashes result + fprintf(fo, "START STREAM\n"); + const char *ptr = info.mResultsStream; + while (*ptr != NULL) + fputc(*ptr++, fo); + fprintf(fo, "END STREAM\n"); + + // New version 2 stuff + fprintf(fo, "GamePhase=%d YellowFlagState=%d SectorFlags=(%d,%d,%d)\n", info.mGamePhase, info.mYellowFlagState, + info.mSectorFlag[0], info.mSectorFlag[1], info.mSectorFlag[2]); + fprintf(fo, "InRealtime=%d StartLight=%d NumRedLights=%d\n", info.mInRealtime, info.mStartLight, info.mNumRedLights); + fprintf(fo, "PlayerName=%s PlrFileName=%s\n", info.mPlayerName, info.mPlrFileName); + fprintf(fo, "DarkCloud=%.2f Raining=%.2f AmbientTemp=%.1f TrackTemp=%.1f\n", info.mDarkCloud, info.mRaining, info.mAmbientTemp, info.mTrackTemp); + fprintf(fo, "Wind=(%.1f,%.1f,%.1f) MinPathWetness=%.2f MaxPathWetness=%.2f\n", info.mWind.x, info.mWind.y, info.mWind.z, info.mMinPathWetness, info.mMaxPathWetness); + + // Print vehicle info + for (long i = 0; i < info.mNumVehicles; ++i) + { + VehicleScoringInfoV01 &vinfo = info.mVehicle[i]; + fprintf(fo, "Driver %d: %s\n", i, vinfo.mDriverName); + fprintf(fo, " ID=%d Vehicle=%s\n", vinfo.mID, vinfo.mVehicleName); + fprintf(fo, " Laps=%d Sector=%d FinishStatus=%d\n", vinfo.mTotalLaps, vinfo.mSector, vinfo.mFinishStatus); + fprintf(fo, " LapDist=%.1f PathLat=%.2f RelevantTrackEdge=%.2f\n", vinfo.mLapDist, vinfo.mPathLateral, vinfo.mTrackEdge); + fprintf(fo, " Best=(%.3f, %.3f, %.3f)\n", vinfo.mBestSector1, vinfo.mBestSector2, vinfo.mBestLapTime); + fprintf(fo, " Last=(%.3f, %.3f, %.3f)\n", vinfo.mLastSector1, vinfo.mLastSector2, vinfo.mLastLapTime); + fprintf(fo, " Current Sector 1 = %.3f, Current Sector 2 = %.3f\n", vinfo.mCurSector1, vinfo.mCurSector2); + fprintf(fo, " Pitstops=%d, Penalties=%d\n", vinfo.mNumPitstops, vinfo.mNumPenalties); + + // New version 2 stuff + fprintf(fo, " IsPlayer=%d Control=%d InPits=%d LapStartET=%.3f\n", vinfo.mIsPlayer, vinfo.mControl, vinfo.mInPits, vinfo.mLapStartET); + fprintf(fo, " Place=%d VehicleClass=%s\n", vinfo.mPlace, vinfo.mVehicleClass); + fprintf(fo, " TimeBehindNext=%.3f LapsBehindNext=%d\n", vinfo.mTimeBehindNext, vinfo.mLapsBehindNext); + fprintf(fo, " TimeBehindLeader=%.3f LapsBehindLeader=%d\n", vinfo.mTimeBehindLeader, vinfo.mLapsBehindLeader); + fprintf(fo, " Pos=(%.3f,%.3f,%.3f)\n", vinfo.mPos.x, vinfo.mPos.y, vinfo.mPos.z); + + // Forward is roughly in the -z direction (although current pitch of car may cause some y-direction velocity) + fprintf(fo, " LocalVel=(%.2f,%.2f,%.2f)\n", vinfo.mLocalVel.x, vinfo.mLocalVel.y, vinfo.mLocalVel.z); + fprintf(fo, " LocalAccel=(%.1f,%.1f,%.1f)\n", vinfo.mLocalAccel.x, vinfo.mLocalAccel.y, vinfo.mLocalAccel.z); + + // Orientation matrix is left-handed + fprintf(fo, " [%6.3f,%6.3f,%6.3f]\n", vinfo.mOri[0].x, vinfo.mOri[0].y, vinfo.mOri[0].z); + fprintf(fo, " [%6.3f,%6.3f,%6.3f]\n", vinfo.mOri[1].x, vinfo.mOri[1].y, vinfo.mOri[1].z); + fprintf(fo, " [%6.3f,%6.3f,%6.3f]\n", vinfo.mOri[2].x, vinfo.mOri[2].y, vinfo.mOri[2].z); + fprintf(fo, " LocalRot=(%.3f,%.3f,%.3f)\n", vinfo.mLocalRot.x, vinfo.mLocalRot.y, vinfo.mLocalRot.z); + fprintf(fo, " LocalRotAccel=(%.2f,%.2f,%.2f)\n", vinfo.mLocalRotAccel.x, vinfo.mLocalRotAccel.y, vinfo.mLocalRotAccel.z); + } + + // Delimit sections + fprintf(fo, "\n"); + + // Close file + fclose(fo); + } +} + +bool RFServerPlugin::AccessPitMenu(PitMenuV01 &info) +{ + return false; +} \ No newline at end of file diff --git a/VC11/InternalsPlugin.sln b/VC11/InternalsPlugin.sln new file mode 100644 index 0000000..68dc235 --- /dev/null +++ b/VC11/InternalsPlugin.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InternalsPlugin", "InternalsPlugin.vcxproj", "{D0C09F9B-E1D6-4A04-B698-190F52BBA156}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Debug|Win32.ActiveCfg = Debug|Win32 + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Debug|Win32.Build.0 = Debug|Win32 + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Debug|x64.ActiveCfg = Debug|x64 + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Debug|x64.Build.0 = Debug|x64 + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Release|Win32.ActiveCfg = Release|Win32 + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Release|Win32.Build.0 = Release|Win32 + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Release|x64.ActiveCfg = Release|x64 + {D0C09F9B-E1D6-4A04-B698-190F52BBA156}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/VC11/InternalsPlugin.vcxproj b/VC11/InternalsPlugin.vcxproj new file mode 100644 index 0000000..3d98b10 --- /dev/null +++ b/VC11/InternalsPlugin.vcxproj @@ -0,0 +1,282 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {D0C09F9B-E1D6-4A04-B698-190F52BBA156} + + + + DynamicLibrary + v110 + false + MultiByte + + + DynamicLibrary + v110 + false + MultiByte + + + DynamicLibrary + v110 + false + MultiByte + + + DynamicLibrary + v110 + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>11.0.60610.1 + + + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + false + + + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + false + + + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + false + + + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + false + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/InternalsPlugin.tlb + + + + MaxSpeed + OnlyExplicitInline + ..\include + WIN32;NDEBUG;_WINDOWS;_USRDLL;INTERNALSPLUGIN_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + true + $(Platform)\$(Configuration)\InternalsPlugin.pch + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + Level3 + true + Fast + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + $(Platform)\$(Configuration)\InternalsPlugin.dll + true + $(Platform)\$(Configuration)\InternalsPlugin.lib + MachineX86 + $(Platform)\$(Configuration)\InternalsPlugin.pdb + + + true + .\Release/InternalsPlugin.bsc + + + + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + .\Release/InternalsPlugin.tlb + + + + + MaxSpeed + OnlyExplicitInline + ..\include + WIN32;NDEBUG;_WINDOWS;_USRDLL;INTERNALSPLUGIN_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + true + $(Platform)\$(Configuration)\InternalsPlugin.pch + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + Level3 + true + Fast + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + $(Platform)\$(Configuration)\InternalsPlugin.dll + true + $(Platform)\$(Configuration)\InternalsPlugin.lib + $(Platform)\$(Configuration)\InternalsPlugin.pdb + + + true + .\Release/InternalsPlugin.bsc + + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/InternalsPlugin.tlb + + + + Disabled + ..\include + WIN32;_DEBUG;_WINDOWS;_USRDLL;INTERNALSPLUGIN_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreaded + $(Platform)\$(Configuration)\InternalsPlugin.pch + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + Level3 + true + EditAndContinue + Fast + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + $(Platform)\$(Configuration)\InternalsPlugin.dll + true + true + $(Platform)\$(Configuration)\InternalsPlugin.pdb + $(Platform)\$(Configuration)\InternalsPlugin.lib + MachineX86 + + + true + .\Debug/InternalsPlugin.bsc + + + + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + .\Debug/InternalsPlugin.tlb + + + + + Disabled + ..\include + WIN32;_DEBUG;_WINDOWS;_USRDLL;INTERNALSPLUGIN_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreaded + $(Platform)\$(Configuration)\InternalsPlugin.pch + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + Level3 + true + ProgramDatabase + Fast + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + $(Platform)\$(Configuration)\InternalsPlugin.dll + true + true + $(Platform)\$(Configuration)\InternalsPlugin.pdb + $(Platform)\$(Configuration)\InternalsPlugin.lib + + + true + .\Debug/InternalsPlugin.bsc + + + + + + + + + + + + + + + + + + \ No newline at end of file