예제 #1
0
        private int readRawData(byte[] rawData)
        {
            // unpack the packet header manually before attempting to load into a struct
            uint packetNumber                        = BitConverter.ToUInt32(rawData, 0);
            uint categoryPacketNumber                = BitConverter.ToUInt32(rawData, 4);
            int  partialPacketIndexBytes             = rawData[8];
            int  partialPacketNumber                 = rawData[9];
            EUDPStreamerPacketHandlerType packetType = (EUDPStreamerPacketHandlerType)rawData[10];
            int packetVersion                        = rawData[11];

            int frameLength = 0;

            switch (packetType)
            {
            case EUDPStreamerPacketHandlerType.eCarPhysics:
                telemPacketCount++;
                if (telemPacketCount > packetCountAtStartOfNextRateCheck)
                {
                    lastPacketRateEstimate = (int)((float)TimeSpan.TicksPerSecond * (float)(telemPacketCount - packetCountAtStartOfCurrentRateCheck) / (float)(DateTime.UtcNow.Ticks - ticksAtStartOfCurrentPacketRateCheck));
                    Console.WriteLine("Packet rate = " + lastPacketRateEstimate +
                                      "Hz, totals:" +
                                      "\rtelem = " + telemPacketCount +
                                      "\rraceDefinition = " + raceDefinitionPacketCount +
                                      "\rparticipants = " + participantsPacketCount +
                                      "\rtimings = " + timingsPacketCount +
                                      "\rgameState = " + gameStatePacketCount +
                                      "\rweather = " + weatherStatePacketCount +
                                      "\rvehicleNames = " + vehicleNamesPacketCount +
                                      "\rtimeStats = " + timeStatsPacketCount +
                                      "\rparticipantVehicleNames = " + participantVehicleNamesPacketCount +
                                      "\rin sequence = " + inSequenceTelemCount + " oos accepted = " + acceptedOutOfSequenceTelemCount + " oos rejected = " + discardedTelemCount);
                    packetCountAtStartOfCurrentRateCheck = telemPacketCount;
                    packetCountAtStartOfNextRateCheck    = packetCountAtStartOfCurrentRateCheck + packetRateCheckInterval;
                    ticksAtStartOfCurrentPacketRateCheck = DateTime.UtcNow.Ticks;
                }
                frameLength = UDPPacketSizes.telemetryPacketSize;
                Boolean sequenceCheckOK = isNextInSequence(packetNumber);
                if (sequenceCheckOK)
                {
                    inSequenceTelemCount++;
                }
                if (strictPacketOrdering && !sequenceCheckOK)
                {
                    discardedTelemCount++;
                }
                else
                {
                    GCHandle telemHandle = GCHandle.Alloc(rawData.Take(frameLength).ToArray(), GCHandleType.Pinned);
                    try
                    {
                        sTelemetryData telem = (sTelemetryData)Marshal.PtrToStructure(telemHandle.AddrOfPinnedObject(), typeof(sTelemetryData));
                        if (sequenceCheckOK || !telemIsOutOfSequence(telem))
                        {
                            buttonsState = ConvertBytesToBoolArray(telem.sDPad, telem.sJoyPad1, telem.sJoyPad2);
                            lastSequenceNumberForTelemPacket = (int)packetNumber;
                            workingGameState = StructHelper.MergeWithExistingState(workingGameState, telem);
                            newSpotterData   = true;
                        }
                    }
                    finally
                    {
                        telemHandle.Free();
                    }
                }
                break;

            case EUDPStreamerPacketHandlerType.eRaceDefinition:
                raceDefinitionPacketCount++;
                frameLength = UDPPacketSizes.raceDataPacketSize;
                GCHandle raceDefHandle = GCHandle.Alloc(rawData.Take(frameLength).ToArray(), GCHandleType.Pinned);
                try
                {
                    sRaceData raceDefinition = (sRaceData)Marshal.PtrToStructure(raceDefHandle.AddrOfPinnedObject(), typeof(sRaceData));
                    workingGameState = StructHelper.MergeWithExistingState(workingGameState, raceDefinition);
                }
                finally
                {
                    raceDefHandle.Free();
                }
                break;

            case EUDPStreamerPacketHandlerType.eParticipants:
                participantsPacketCount++;
                frameLength = UDPPacketSizes.participantsDataPacketSize;
                GCHandle participantsHandle = GCHandle.Alloc(rawData.Take(frameLength).ToArray(), GCHandleType.Pinned);
                try
                {
                    sParticipantsData participants = (sParticipantsData)Marshal.PtrToStructure(participantsHandle.AddrOfPinnedObject(), typeof(sParticipantsData));
                    workingGameState = StructHelper.MergeWithExistingState(workingGameState, participants);
                }
                finally
                {
                    participantsHandle.Free();
                }
                break;

            case EUDPStreamerPacketHandlerType.eTimings:
                timingsPacketCount++;
                frameLength = UDPPacketSizes.timingsDataPacketSize;
                GCHandle timingsHandle = GCHandle.Alloc(rawData.Take(frameLength).ToArray(), GCHandleType.Pinned);
                try
                {
                    sTimingsData timings = (sTimingsData)Marshal.PtrToStructure(timingsHandle.AddrOfPinnedObject(), typeof(sTimingsData));
                    workingGameState = StructHelper.MergeWithExistingState(workingGameState, timings);
                }
                finally
                {
                    timingsHandle.Free();
                }
                break;

            case EUDPStreamerPacketHandlerType.eGameState:
                gameStatePacketCount++;
                frameLength = UDPPacketSizes.gameStateDataPacketSize;
                GCHandle gameStateHandle = GCHandle.Alloc(rawData.Take(frameLength).ToArray(), GCHandleType.Pinned);
                try
                {
                    sGameStateData gameState = (sGameStateData)Marshal.PtrToStructure(gameStateHandle.AddrOfPinnedObject(), typeof(sGameStateData));
                    workingGameState = StructHelper.MergeWithExistingState(workingGameState, gameState);
                }
                finally
                {
                    gameStateHandle.Free();
                }
                break;

            case EUDPStreamerPacketHandlerType.eWeatherState:
                weatherStatePacketCount++;
                Console.WriteLine("Got an undocumented and unsupported weather packet");
                break;

            case EUDPStreamerPacketHandlerType.eVehicleNames:
                weatherStatePacketCount++;
                Console.WriteLine("Got an undocumented and unsupported vehicle names packet");
                break;

            case EUDPStreamerPacketHandlerType.eTimeStats:
                participantsPacketCount++;
                frameLength = UDPPacketSizes.timeStatsPacketSize;
                GCHandle timeStatsHandle = GCHandle.Alloc(rawData.Take(frameLength).ToArray(), GCHandleType.Pinned);
                try
                {
                    sTimeStatsData timeStatsData = (sTimeStatsData)Marshal.PtrToStructure(timeStatsHandle.AddrOfPinnedObject(), typeof(sTimeStatsData));
                    workingGameState = StructHelper.MergeWithExistingState(workingGameState, timeStatsData);
                }
                finally
                {
                    timeStatsHandle.Free();
                }
                break;

            case EUDPStreamerPacketHandlerType.eParticipantVehicleNames:
                participantsPacketCount++;
                frameLength = UDPPacketSizes.participantVehicleNamesPacketSize;
                GCHandle vehNamesHandle = GCHandle.Alloc(rawData.Take(frameLength).ToArray(), GCHandleType.Pinned);
                try
                {
                    sParticipantVehicleNamesData participantVehicleNames = (sParticipantVehicleNamesData)Marshal.PtrToStructure(vehNamesHandle.AddrOfPinnedObject(), typeof(sParticipantVehicleNamesData));
                    workingGameState = StructHelper.MergeWithExistingState(workingGameState, participantVehicleNames);
                }
                finally
                {
                    vehNamesHandle.Free();
                }
                break;
            }
            return(frameLength);
        }
예제 #2
0
        public static pCars2APIStruct MergeWithExistingState(pCars2APIStruct existingState, sRaceData raceData)
        {
            Boolean isTimedSession = (raceData.sLapsTimeInEvent >> 15) == 1;
            int     sessionLength  = raceData.sLapsTimeInEvent / 2; // need the bottom bits of this short here - is it valid to just halve it?

            if (isTimedSession)
            {
                existingState.mLapsInEvent = (uint)sessionLength;
                existingState.mSessionLengthTimeFromGame = 0;
            }
            else
            {
                existingState.mSessionLengthTimeFromGame = 300 * (uint)sessionLength;  // *300 because this is in 5 minutes blocks
                existingState.mLapsInEvent = 0;
            }
            existingState.mTrackLength = raceData.sTrackLength;

            existingState.mWorldFastestLapTime        = raceData.sWorldFastestLapTime;
            existingState.mWorldFastestSector1Time    = raceData.sWorldFastestSector1Time;
            existingState.mWorldFastestSector2Time    = raceData.sWorldFastestSector2Time;
            existingState.mWorldFastestSector3Time    = raceData.sWorldFastestSector3Time;
            existingState.mPersonalFastestLapTime     = raceData.sPersonalFastestLapTime;
            existingState.mPersonalFastestSector1Time = raceData.sPersonalFastestSector1Time;
            existingState.mPersonalFastestSector2Time = raceData.sPersonalFastestSector2Time;
            existingState.mPersonalFastestSector3Time = raceData.sPersonalFastestSector3Time;

            existingState.mTrackLocation            = raceData.sTrackLocation;
            existingState.mTrackVariation           = raceData.sTrackVariation;
            existingState.mTranslatedTrackLocation  = raceData.sTranslatedTrackLocation;
            existingState.mTranslatedTrackVariation = raceData.sTranslatedTrackVariation;

            existingState.mEnforcedPitStopLap = raceData.sEnforcedPitStopLap;
            return(existingState);
        }