コード例 #1
0
 public static pCarsAPIStruct MergeWithExistingState(pCarsAPIStruct existingState, sParticipantInfoStrings udpParticipantStrings)
 {
     existingState.mCarClassName   = udpParticipantStrings.sCarClassName;
     existingState.mCarName        = udpParticipantStrings.sCarName;
     existingState.mTrackLocation  = udpParticipantStrings.sTrackLocation;
     existingState.mTrackVariation = udpParticipantStrings.sTrackVariation;
     for (int i = 0; i < udpParticipantStrings.sName.Count(); i++)
     {
         String name = getNameFromBytes(udpParticipantStrings.sName[i].nameByteArray);
         existingState.mParticipantData[i].mIsActive = name != null && name.Length > 0;
         existingState.mParticipantData[i].mName     = name;
     }
     return(existingState);
 }
コード例 #2
0
 public static pCarsAPIStruct MergeWithExistingState(pCarsAPIStruct existingState, sParticipantInfoStringsAdditional udpAdditionalStrings)
 {
     if (existingState.mParticipantData == null)
     {
         existingState.mParticipantData = new pCarsAPIParticipantStruct[udpAdditionalStrings.sName.Count()];
     }
     for (int i = 0; i < udpAdditionalStrings.sName.Count(); i++)
     {
         String name = getNameFromBytes(udpAdditionalStrings.sName[i].nameByteArray);
         // TODO: will the mIsActive flag always have been set by the time we reach here?
         existingState.mParticipantData[i + udpAdditionalStrings.sOffset].mIsActive = name != null && name.Length > 0;
         existingState.mParticipantData[i + udpAdditionalStrings.sOffset].mName     = name;
     }
     return(existingState);
 }
コード例 #3
0
 public override Object ReadGameData(Boolean forSpotter)
 {
     lock (this)
     {
         pCarsAPIStruct _pcarsapistruct = new pCarsAPIStruct();
         if (!initialised)
         {
             if (!InitialiseInternal())
             {
                 throw new GameDataReadException("Failed to initialise shared memory");
             }
         }
         try
         {
             using (var sharedMemoryStreamView = memoryMappedFile.CreateViewStream())
             {
                 BinaryReader _SharedMemoryStream = new BinaryReader(sharedMemoryStreamView);
                 sharedMemoryReadBuffer = _SharedMemoryStream.ReadBytes(sharedmemorysize);
                 handle = GCHandle.Alloc(sharedMemoryReadBuffer, GCHandleType.Pinned);
                 _pcarsapistruct = (pCarsAPIStruct)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(pCarsAPIStruct));
                 //Console.WriteLine(_pcarsapistruct.mSpeed);
                 handle.Free();
             }
             PCarsStructWrapper structWrapper = new PCarsStructWrapper();
             structWrapper.ticksWhenRead = DateTime.Now.Ticks;
             structWrapper.data = _pcarsapistruct;
             if (!forSpotter && dumpToFile && dataToDump != null && _pcarsapistruct.mTrackLocation != null &&
                 _pcarsapistruct.mTrackLocation.Length > 0)
             {
                 dataToDump.Add(structWrapper);
             }
             return structWrapper;
         }
         catch (Exception ex)
         {
             throw new GameDataReadException(ex.Message, ex);
         }
     }
 }
コード例 #4
0
        public static pCarsAPIStruct MergeWithExistingState(pCarsAPIStruct existingState, sTelemetryData udpTelemetryData)
        {
            existingState.hasNewPositionData = false;
            existingState.mGameState         = (uint)udpTelemetryData.sGameSessionState & 7;
            existingState.mSessionState      = (uint)udpTelemetryData.sGameSessionState >> 4;
            existingState.mRaceState         = (uint)udpTelemetryData.sRaceStateFlags & 7;

            // Participant Info
            existingState.mViewedParticipantIndex = udpTelemetryData.sViewedParticipantIndex;
            existingState.mNumParticipants        = udpTelemetryData.sNumParticipants;

            // Unfiltered Input
            existingState.mUnfilteredThrottle = (float)udpTelemetryData.sUnfilteredThrottle / 255f;
            existingState.mUnfilteredBrake    = (float)udpTelemetryData.sUnfilteredBrake / 255f;
            existingState.mUnfilteredSteering = (float)udpTelemetryData.sUnfilteredSteering / 127f;
            existingState.mUnfilteredClutch   = (float)udpTelemetryData.sUnfilteredClutch / 255f;

            existingState.mLapsInEvent = udpTelemetryData.sLapsInEvent;
            existingState.mTrackLength = udpTelemetryData.sTrackLength;

            // Timing & Scoring
            existingState.mLapInvalidated             = (udpTelemetryData.sRaceStateFlags >> 3 & 1) == 1;
            existingState.mSessionFastestLapTime      = udpTelemetryData.sBestLapTime;
            existingState.mLastLapTime                = udpTelemetryData.sLastLapTime;
            existingState.mCurrentTime                = udpTelemetryData.sCurrentTime;
            existingState.mSplitTimeAhead             = udpTelemetryData.sSplitTimeAhead;
            existingState.mSplitTimeBehind            = udpTelemetryData.sSplitTimeBehind;
            existingState.mSplitTime                  = udpTelemetryData.sSplitTime;
            existingState.mEventTimeRemaining         = udpTelemetryData.sEventTimeRemaining;
            existingState.mPersonalFastestLapTime     = udpTelemetryData.sPersonalFastestLapTime;
            existingState.mWorldFastestLapTime        = udpTelemetryData.sWorldFastestLapTime;
            existingState.mCurrentSector1Time         = udpTelemetryData.sCurrentSector1Time;
            existingState.mCurrentSector2Time         = udpTelemetryData.sCurrentSector2Time;
            existingState.mCurrentSector3Time         = udpTelemetryData.sCurrentSector3Time;
            existingState.mSessionFastestSector1Time  = udpTelemetryData.sFastestSector1Time;
            existingState.mSessionFastestSector2Time  = udpTelemetryData.sFastestSector2Time;
            existingState.mSessionFastestSector3Time  = udpTelemetryData.sFastestSector3Time;
            existingState.mPersonalFastestSector1Time = udpTelemetryData.sPersonalFastestSector1Time;
            existingState.mPersonalFastestSector2Time = udpTelemetryData.sPersonalFastestSector2Time;
            existingState.mPersonalFastestSector3Time = udpTelemetryData.sPersonalFastestSector3Time;
            existingState.mWorldFastestSector1Time    = udpTelemetryData.sWorldFastestSector1Time;
            existingState.mWorldFastestSector2Time    = udpTelemetryData.sWorldFastestSector2Time;
            existingState.mWorldFastestSector3Time    = udpTelemetryData.sWorldFastestSector3Time;

            // Flags
            existingState.mHighestFlagColour = (uint)udpTelemetryData.sHighestFlag & 7;
            existingState.mHighestFlagReason = (uint)udpTelemetryData.sHighestFlag >> 3 & 3;

            // Pit Info
            existingState.mPitMode     = (uint)udpTelemetryData.sPitModeSchedule & 7;
            existingState.mPitSchedule = (uint)udpTelemetryData.sPitModeSchedule >> 3 & 3;

            // Car State
            existingState.mCarFlags         = udpTelemetryData.sCarFlags;
            existingState.mOilTempCelsius   = udpTelemetryData.sOilTempCelsius;
            existingState.mOilPressureKPa   = udpTelemetryData.sOilPressureKPa;
            existingState.mWaterTempCelsius = udpTelemetryData.sWaterTempCelsius;
            existingState.mWaterPressureKPa = udpTelemetryData.sWaterPressureKpa;
            existingState.mFuelPressureKPa  = udpTelemetryData.sFuelPressureKpa;
            existingState.mFuelLevel        = udpTelemetryData.sFuelLevel;
            existingState.mFuelCapacity     = udpTelemetryData.sFuelCapacity;
            existingState.mSpeed            = udpTelemetryData.sSpeed;
            existingState.mRPM            = udpTelemetryData.sRpm;
            existingState.mMaxRPM         = udpTelemetryData.sMaxRpm;
            existingState.mBrake          = (float)udpTelemetryData.sBrake / 255f;
            existingState.mThrottle       = (float)udpTelemetryData.sThrottle / 255f;
            existingState.mClutch         = (float)udpTelemetryData.sClutch / 255f;
            existingState.mSteering       = (float)udpTelemetryData.sSteering / 127f;
            existingState.mGear           = udpTelemetryData.sGearNumGears & 15;
            existingState.mNumGears       = udpTelemetryData.sGearNumGears >> 4;
            existingState.mOdometerKM     = udpTelemetryData.sOdometerKM;
            existingState.mAntiLockActive = (udpTelemetryData.sRaceStateFlags >> 4 & 1) == 1;
            existingState.mBoostActive    = (udpTelemetryData.sRaceStateFlags >> 5 & 1) == 1;
            existingState.mBoostAmount    = udpTelemetryData.sBoostAmount;

            // Motion & Device Related
            existingState.mOrientation       = udpTelemetryData.sOrientation;
            existingState.mLocalVelocity     = udpTelemetryData.sLocalVelocity;
            existingState.mWorldVelocity     = udpTelemetryData.sWorldVelocity;
            existingState.mAngularVelocity   = udpTelemetryData.sAngularVelocity;
            existingState.mLocalAcceleration = udpTelemetryData.sLocalAcceleration;
            existingState.mWorldAcceleration = udpTelemetryData.sWorldAcceleration;
            existingState.mExtentsCentre     = udpTelemetryData.sExtentsCentre;


            existingState.mTyreFlags             = toUIntArray(udpTelemetryData.sTyreFlags);
            existingState.mTerrain               = toUIntArray(udpTelemetryData.sTerrain);
            existingState.mTyreY                 = udpTelemetryData.sTyreY;
            existingState.mTyreRPS               = udpTelemetryData.sTyreRPS;
            existingState.mTyreSlipSpeed         = udpTelemetryData.sTyreSlipSpeed;
            existingState.mTyreTemp              = toFloatArray(udpTelemetryData.sTyreTemp, 255);
            existingState.mTyreGrip              = toFloatArray(udpTelemetryData.sTyreGrip, 255);
            existingState.mTyreHeightAboveGround = udpTelemetryData.sTyreHeightAboveGround;
            existingState.mTyreLateralStiffness  = udpTelemetryData.sTyreLateralStiffness;
            existingState.mTyreWear              = toFloatArray(udpTelemetryData.sTyreWear, 255);
            existingState.mBrakeDamage           = toFloatArray(udpTelemetryData.sBrakeDamage, 255);
            existingState.mSuspensionDamage      = toFloatArray(udpTelemetryData.sSuspensionDamage, 255);
            existingState.mBrakeTempCelsius      = toFloatArray(udpTelemetryData.sBrakeTempCelsius, 1);
            existingState.mTyreTreadTemp         = toFloatArray(udpTelemetryData.sTyreTreadTemp, 1);
            existingState.mTyreLayerTemp         = toFloatArray(udpTelemetryData.sTyreLayerTemp, 1);
            existingState.mTyreCarcassTemp       = toFloatArray(udpTelemetryData.sTyreCarcassTemp, 1);
            existingState.mTyreRimTemp           = toFloatArray(udpTelemetryData.sTyreRimTemp, 1);
            existingState.mTyreInternalAirTemp   = toFloatArray(udpTelemetryData.sTyreInternalAirTemp, 1);
            existingState.mWheelLocalPosition    = udpTelemetryData.sWheelLocalPositionY;
            existingState.mRideHeight            = udpTelemetryData.sRideHeight;
            existingState.mSuspensionTravel      = udpTelemetryData.sSuspensionTravel;
            existingState.mSuspensionVelocity    = udpTelemetryData.sSuspensionVelocity;
            existingState.mAirPressure           = toFloatArray(udpTelemetryData.sAirPressure, 1);

            existingState.mEngineSpeed        = udpTelemetryData.sEngineSpeed;
            existingState.mEngineTorque       = udpTelemetryData.sEngineTorque;
            existingState.mEnforcedPitStopLap = (uint)udpTelemetryData.sEnforcedPitStopLap;

            // Car Damage
            existingState.mCrashState   = udpTelemetryData.sCrashState;
            existingState.mAeroDamage   = (float)udpTelemetryData.sAeroDamage / 255f;
            existingState.mEngineDamage = (float)udpTelemetryData.sEngineDamage / 255f;

            // Weather
            existingState.mAmbientTemperature = udpTelemetryData.sAmbientTemperature;
            existingState.mTrackTemperature   = udpTelemetryData.sTrackTemperature;
            existingState.mRainDensity        = (float)udpTelemetryData.sRainDensity / 255f;
            existingState.mWindSpeed          = udpTelemetryData.sWindSpeed * 2;
            existingState.mWindDirectionX     = (float)udpTelemetryData.sWindDirectionX / 127f;
            existingState.mWindDirectionY     = (float)udpTelemetryData.sWindDirectionY / 127f;
            //existingState.mCloudBrightness = udpTelemetryData.sCloudBrightness / 255;

            if (existingState.mParticipantData == null)
            {
                existingState.mParticipantData = new pCarsAPIParticipantStruct[udpTelemetryData.sParticipantInfo.Count()];
            }
            for (int i = 0; i < udpTelemetryData.sParticipantInfo.Count(); i++)
            {
                sParticipantInfo          newPartInfo      = udpTelemetryData.sParticipantInfo[i];
                Boolean                   isActive         = (newPartInfo.sRacePosition >> 7) == 1;
                pCarsAPIParticipantStruct existingPartInfo = existingState.mParticipantData[i];
                existingPartInfo.mIsActive = isActive;
                if (isActive)
                {
                    existingPartInfo.mCurrentLap         = newPartInfo.sCurrentLap;
                    existingPartInfo.mCurrentLapDistance = newPartInfo.sCurrentLapDistance;
                    existingPartInfo.mLapsCompleted      = (uint)newPartInfo.sLapsCompleted & 127;
                    // TODO: there's a 'lapInvalidated' flag here but nowhere to put it in the existing struct
                    Boolean lapInvalidated = (newPartInfo.sLapsCompleted >> 7) == 1;
                    existingPartInfo.mRacePosition  = (uint)newPartInfo.sRacePosition & 127;
                    existingPartInfo.mCurrentSector = (uint)newPartInfo.sSector & 7;

                    // and now the bit magic for the extra position precision...
                    float[] newWorldPositions = toFloatArray(newPartInfo.sWorldPosition, 1);
                    float   xAdjustment       = ((float)((uint)newPartInfo.sSector >> 3 & 3)) / 4f;
                    float   zAdjustment       = ((float)((uint)newPartInfo.sSector >> 5 & 3)) / 4f;
                    newWorldPositions[0] = newWorldPositions[0] + xAdjustment;
                    newWorldPositions[2] = newWorldPositions[2] + zAdjustment;
                    if (!existingState.hasNewPositionData && i != udpTelemetryData.sViewedParticipantIndex &&
                        (existingPartInfo.mWorldPosition == null || (newWorldPositions[0] != existingPartInfo.mWorldPosition[0] || newWorldPositions[2] != existingPartInfo.mWorldPosition[2])))
                    {
                        existingState.hasNewPositionData = true;
                    }
                    existingPartInfo.mWorldPosition = newWorldPositions;

                    // TODO: LastSectorTime is now in the UDP data, but there's no slot for this in the participants struct
                    // existingPartInfo.mLastSectorTime = newPartInfo.sLastSectorTime;
                }
                else
                {
                    existingPartInfo.mWorldPosition = new float[] { 0, 0, 0 };
                }
                existingState.mParticipantData[i] = existingPartInfo;
            }

            // TODO: buttons
            return(existingState);
        }
コード例 #5
0
 private int readFromOffset(int offset, byte[] rawData)
 {
     totalPacketCount++;
     if (totalPacketCount == estimateRateStartPacket)
     {
         ticksAtRateEstimateStart = DateTime.Now.Ticks;
     }
     else if (totalPacketCount == estimateRateEndPacket && ticksAtRateEstimateStart > 0)
     {
         rateEstimate = (float)(TimeSpan.TicksPerSecond * (estimateRateEndPacket - estimateRateStartPacket)) / (float)(DateTime.Now.Ticks - ticksAtRateEstimateStart);
     }
     // the first 2 bytes are the version - discard it for now
     int frameTypeAndSequence = rawData[offset + 2];
     int frameType = frameTypeAndSequence & 3;
     int sequence = frameTypeAndSequence >> 2;
     int frameLength = 0;
     if (frameType == 0)
     {
         telemPacketCount++;
         frameLength = sTelemetryData_PacketSize;
         Boolean sequenceCheckOK = isNextInSequence(sequence);
         if (strictPacketOrdering && !sequenceCheckOK)
         {
             discardedTelemCount++;
         }
         else
         {
             handle = GCHandle.Alloc(rawData.Skip(offset).Take(frameLength).ToArray(), GCHandleType.Pinned);
             sTelemetryData telem = (sTelemetryData)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(sTelemetryData));
             if (sequenceCheckOK || !telemIsOutOfSequence(telem))
             {
                 buttonsState = ConvertByteToBoolArray(telem.sDPad);
                 lastSequenceNumberForTelemPacket = sequence;
                 workingGameState = StructHelper.MergeWithExistingState(workingGameState, telem);
                 newSpotterData = workingGameState.hasNewPositionData;
                 handle.Free();
             }
         }
     }
     else if (frameType == 1)
     {
         frameLength = sParticipantInfoStrings_PacketSize;
         handle = GCHandle.Alloc(rawData.Skip(offset).Take(frameLength).ToArray(), GCHandleType.Pinned);
         sParticipantInfoStrings strings = (sParticipantInfoStrings)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(sParticipantInfoStrings));
         workingGameState = StructHelper.MergeWithExistingState(workingGameState, strings);
         handle.Free();
     }
     else if (frameType == 2)
     {
         frameLength = sParticipantInfoStringsAdditional_PacketSize;
         handle = GCHandle.Alloc(rawData.Skip(offset).Take(frameLength).ToArray(), GCHandleType.Pinned);
         sParticipantInfoStringsAdditional additional = (sParticipantInfoStringsAdditional)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(sParticipantInfoStringsAdditional));
         workingGameState = StructHelper.MergeWithExistingState(workingGameState, additional);
         handle.Free();
     }
     return frameLength + offset;
 }
コード例 #6
0
 public override Object ReadGameData(Boolean forSpotter)
 {
     CrewChiefV3.PCars.PCarsSharedMemoryReader.PCarsStructWrapper structWrapper = new CrewChiefV3.PCars.PCarsSharedMemoryReader.PCarsStructWrapper();
     structWrapper.ticksWhenRead = DateTime.Now.Ticks;
     lock (this)
     {
         if (!initialised)
         {
             if (!InitialiseInternal())
             {
                 throw new GameDataReadException("Failed to initialise UDP client");
             }
         }
         previousGameState = StructHelper.Clone(currentGameState);
         currentGameState = StructHelper.Clone(workingGameState);
         if (forSpotter)
         {
             newSpotterData = false;
         }
     }
     structWrapper.data = currentGameState;
     if (!forSpotter && dumpToFile && dataToDump != null && currentGameState.mTrackLocation != null &&
         currentGameState.mTrackLocation.Length > 0)
     {
         dataToDump.Add(structWrapper);
     }
     return structWrapper;
 }