예제 #1
0
 public override Object ReadGameData(Boolean forSpotter)
 {
     CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper structWrapper = new CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper();
     structWrapper.ticksWhenRead = DateTime.UtcNow.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);
 }
예제 #2
0
 public override Object ReadGameDataFromFile(String filename)
 {
     if (dataReadFromFile == null || filename != lastReadFileName)
     {
         dataReadFromFileIndex = 0;
         dataReadFromFile      = DeSerializeObject <CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper[]>(dataFilesPath + filename);
         lastReadFileName      = filename;
     }
     if (dataReadFromFile != null && dataReadFromFile.Length > dataReadFromFileIndex)
     {
         CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper structWrapperData = dataReadFromFile[dataReadFromFileIndex];
         dataReadFromFileIndex++;
         return(structWrapperData);
     }
     else
     {
         return(null);
     }
 }
예제 #3
0
 public override Object ReadGameDataFromFile(String filename, int pauseBeforeStart)
 {
     if (dataReadFromFile == null || filename != lastReadFileName)
     {
         dataReadFromFileIndex = 0;
         var filePathResolved = Utilities.ResolveDataFile(this.dataFilesPath, filename);
         dataReadFromFile = DeSerializeObject <CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper[]>(filePathResolved);
         lastReadFileName = filename;
         Thread.Sleep(pauseBeforeStart);
     }
     if (dataReadFromFile != null && dataReadFromFile.Length > dataReadFromFileIndex)
     {
         CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper structWrapperData = dataReadFromFile[dataReadFromFileIndex];
         dataReadFromFileIndex++;
         return(structWrapperData);
     }
     else
     {
         return(null);
     }
 }
예제 #4
0
        public void trigger(Object lastStateObj, Object currentStateObj)
        {
            if (paused)
            {
                return;
            }
            CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper currentWrapper = (CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper)currentStateObj;
            pCarsAPIStruct currentState = currentWrapper.data;

            // game state is 3 for paused, 5 for replay. No idea what 4 is...
            if (currentState.mGameState == (uint)eGameState.GAME_FRONT_END ||
                (currentState.mGameState == (uint)eGameState.GAME_INGAME_PAUSED && !System.Diagnostics.Debugger.IsAttached) ||
                currentState.mGameState == (uint)eGameState.GAME_VIEWING_REPLAY || currentState.mGameState == (uint)eGameState.GAME_EXITED)
            {
                // don't ignore the paused game updates if we're in debug mode
                return;
            }
            CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper previousWrapper = (CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper)lastStateObj;
            pCarsAPIStruct lastState = previousWrapper.data;

            DateTime now = new DateTime(currentWrapper.ticksWhenRead);
            float interval = (float)(((double)currentWrapper.ticksWhenRead - (double)previousWrapper.ticksWhenRead) / (double)TimeSpan.TicksPerSecond);
            if (currentState.mRaceState == (int)eRaceState.RACESTATE_RACING &&
                lastState.mRaceState != (int)eRaceState.RACESTATE_RACING)
            {
                timeToStartSpotting = now.Add(TimeSpan.FromSeconds(timeAfterRaceStartToActivate));
            }
            // this check looks a bit funky... whe we start a practice session, the raceState is not_started
            // until we cross the line for the first time. Which is retarded really.
            if (currentState.mRaceState == (int)eRaceState.RACESTATE_INVALID || now < timeToStartSpotting ||
                (currentState.mSessionState == (int)eSessionState.SESSION_RACE && currentState.mRaceState == (int) eRaceState.RACESTATE_NOT_STARTED))
            {
                return;
            }

            if (enabled && currentState.mNumParticipants > 1 &&
                (enableSpotterInTimetrial || currentState.mSessionState != (uint)eSessionState.SESSION_TIME_ATTACK))
            {
                Tuple<int, pCarsAPIParticipantStruct> playerDataWithIndex = PCarsGameStateMapper.getPlayerDataStruct(currentState.mParticipantData, currentState.mViewedParticipantIndex);
                int playerIndex = playerDataWithIndex.Item1;
                pCarsAPIParticipantStruct playerData = playerDataWithIndex.Item2;
                float[] currentPlayerPosition = new float[] { playerData.mWorldPosition[0], playerData.mWorldPosition[2] };

                if (currentState.mPitMode == (uint)ePitMode.PIT_MODE_NONE)
                {
                    List<float[]> currentOpponentPositions = new List<float[]>();
                    float[] playerVelocityData = new float[3];
                    playerVelocityData[0] = currentState.mSpeed;
                    playerVelocityData[1] = currentState.mWorldVelocity[0];
                    playerVelocityData[2] = currentState.mWorldVelocity[2];

                    for (int i = 0; i < currentState.mParticipantData.Count(); i++)
                    {
                        if (i == playerIndex)
                        {
                            continue;
                        }
                        pCarsAPIParticipantStruct opponentData = currentState.mParticipantData[i];
                        if (opponentData.mIsActive)
                        {
                            float[] currentPositions = new float[] { opponentData.mWorldPosition[0], opponentData.mWorldPosition[2] };
                            currentOpponentPositions.Add(currentPositions);
                        }
                    }
                    if (currentOpponentPositions.Count() > 0)
                    {
                        float playerRotation = currentState.mOrientation[1];
                        if (playerRotation < 0)
                        {
                            playerRotation = (float)(2 * Math.PI) + playerRotation;
                        }
                        playerRotation = (float)(2 * Math.PI) - playerRotation;
                        internalSpotter.triggerInternal(playerRotation, currentPlayerPosition, playerVelocityData, currentOpponentPositions);
                    }
                }
            }
        }
예제 #5
0
        public void trigger(Object lastStateObj, Object currentStateObj)
        {
            if (paused)
            {
                audioPlayer.closeChannel();
                return;
            }
            CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper currentWrapper = (CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper)currentStateObj;
            pCarsAPIStruct currentState = currentWrapper.data;

            // game state is 3 for paused, 5 for replay. No idea what 4 is...
            if (currentState.mGameState == (uint)eGameState.GAME_FRONT_END ||
                (currentState.mGameState == (uint)eGameState.GAME_INGAME_PAUSED && !System.Diagnostics.Debugger.IsAttached) ||
                currentState.mGameState == (uint)eGameState.GAME_VIEWING_REPLAY || currentState.mGameState == (uint)eGameState.GAME_EXITED)
            {
                // don't ignore the paused game updates if we're in debug mode
                audioPlayer.closeChannel();
                return;
            }
            CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper previousWrapper = (CrewChiefV4.PCars.PCarsSharedMemoryReader.PCarsStructWrapper)lastStateObj;
            pCarsAPIStruct lastState = previousWrapper.data;

            DateTime now      = new DateTime(currentWrapper.ticksWhenRead);
            float    interval = (float)(((double)currentWrapper.ticksWhenRead - (double)previousWrapper.ticksWhenRead) / (double)TimeSpan.TicksPerSecond);

            if (currentState.mRaceState == (int)eRaceState.RACESTATE_RACING &&
                lastState.mRaceState != (int)eRaceState.RACESTATE_RACING)
            {
                timeToStartSpotting = now.Add(TimeSpan.FromSeconds(timeAfterRaceStartToActivate));
            }
            // this check looks a bit funky... whe we start a practice session, the raceState is not_started
            // until we cross the line for the first time. Which is retarded really.
            if (currentState.mRaceState == (int)eRaceState.RACESTATE_INVALID || now < timeToStartSpotting ||
                (currentState.mSessionState == (int)eSessionState.SESSION_RACE && currentState.mRaceState == (int)eRaceState.RACESTATE_NOT_STARTED))
            {
                return;
            }

            float currentSpeed  = currentState.mSpeed;
            float previousSpeed = lastState.mSpeed;

            if (enabled && currentState.mParticipantData.Count() > 1)
            {
                Tuple <int, pCarsAPIParticipantStruct> playerDataWithIndex = PCarsGameStateMapper.getPlayerDataStruct(currentState.mParticipantData, currentState.mViewedParticipantIndex);
                int playerIndex = playerDataWithIndex.Item1;
                pCarsAPIParticipantStruct playerData = playerDataWithIndex.Item2;
                float playerX = playerData.mWorldPosition[0];
                float playerY = playerData.mWorldPosition[2];
                if (playerX == 0 || playerY == 0 || playerX == -1 || playerY == -1 ||
                    lastState.mParticipantData == null || lastState.mParticipantData.Length == 0 || lastState.mViewedParticipantIndex < 0)
                {
                    return;
                }
                Tuple <int, pCarsAPIParticipantStruct> previousPlayerDataWithIndex = PCarsGameStateMapper.getPlayerDataStruct(lastState.mParticipantData, lastState.mViewedParticipantIndex);
                pCarsAPIParticipantStruct previousPlayerData = previousPlayerDataWithIndex.Item2;

                if (currentSpeed > minSpeedForSpotterToOperate && currentState.mPitMode == (uint)ePitMode.PIT_MODE_NONE)
                {
                    int carsOnLeft  = 0;
                    int carsOnRight = 0;
                    for (int i = 0; i < currentState.mParticipantData.Count(); i++)
                    {
                        if (i == playerIndex)
                        {
                            continue;
                        }
                        if (carsOnLeft >= 1 && carsOnRight >= 1)
                        {
                            // stop processing - we already know there's a car on both sides
                            break;
                        }

                        pCarsAPIParticipantStruct opponentData = currentState.mParticipantData[i];

                        float previousOpponentX = 0;
                        float previousOpponentY = 0;
                        try
                        {
                            pCarsAPIParticipantStruct previousOpponentData = PCarsGameStateMapper.getParticipantDataForName(lastState.mParticipantData, opponentData.mName, i);
                            previousOpponentX = previousOpponentData.mWorldPosition[0];
                            previousOpponentY = previousOpponentData.mWorldPosition[2];
                        }
                        catch (Exception)
                        {
                            // ignore - the mParticipantData array is frequently full of crap
                        }
                        float currentOpponentX = opponentData.mWorldPosition[0];
                        float currentOpponentY = opponentData.mWorldPosition[2];

                        if (opponentData.mIsActive)
                        {
                            if (currentOpponentX != 0 && currentOpponentY != 0 &&
                                currentOpponentX != -1 && currentOpponentY != -1 &&
                                previousOpponentX != 0 && previousOpponentY != 0 &&
                                previousOpponentX != -1 && previousOpponentY != -1 &&
                                opponentIsRacing(currentOpponentX, currentOpponentY, previousOpponentX, previousOpponentY, playerData, previousPlayerData, interval))
                            {
                                Side side = getSide(currentState.mOrientation[1], playerX, playerY, currentOpponentX, currentOpponentY);
                                if (side == Side.left)
                                {
                                    carsOnLeft++;
                                    if (lastKnownOpponentState.ContainsKey(opponentData.mName))
                                    {
                                        lastKnownOpponentState[opponentData.mName] = Side.left;
                                    }
                                    else
                                    {
                                        lastKnownOpponentState.Add(opponentData.mName, Side.left);
                                    }
                                }
                                else if (side == Side.right)
                                {
                                    carsOnRight++;
                                    if (lastKnownOpponentState.ContainsKey(opponentData.mName))
                                    {
                                        lastKnownOpponentState[opponentData.mName] = Side.right;
                                    }
                                    else
                                    {
                                        lastKnownOpponentState.Add(opponentData.mName, Side.right);
                                    }
                                }
                                else
                                {
                                    if (lastKnownOpponentState.ContainsKey(opponentData.mName))
                                    {
                                        lastKnownOpponentState[opponentData.mName] = Side.none;
                                    }
                                    else
                                    {
                                        lastKnownOpponentState.Add(opponentData.mName, Side.none);
                                    }
                                }
                            }
                            else
                            {
                                // no usable position data, use the last known state
                                if (lastKnownOpponentState.ContainsKey(opponentData.mName))
                                {
                                    int lastStateUseCount = 1;
                                    if (lastKnownOpponentStateUseCounter.ContainsKey(opponentData.mName))
                                    {
                                        lastStateUseCount = lastKnownOpponentStateUseCounter[opponentData.mName] + 1;
                                    }
                                    else
                                    {
                                        lastKnownOpponentStateUseCounter.Add(opponentData.mName, 0);
                                    }
                                    if (lastStateUseCount < maxSavedStateReuse)
                                    {
                                        lastKnownOpponentStateUseCounter[opponentData.mName] = lastStateUseCount;
                                        if (lastKnownOpponentState[opponentData.mName] == Side.left)
                                        {
                                            carsOnLeft++;
                                        }
                                        else if (lastKnownOpponentState[opponentData.mName] == Side.right)
                                        {
                                            carsOnRight++;
                                        }
                                    }
                                    else
                                    {
                                        // we've used too many saved states for this missing opponent position
                                        lastKnownOpponentState.Remove(opponentData.mName);
                                        lastKnownOpponentStateUseCounter.Remove(opponentData.mName);
                                    }
                                }
                            }
                        }
                    }
                    getNextMessage(carsOnLeft, carsOnRight, now);
                    playNextMessage(carsOnLeft, carsOnRight, now);
                    hasCarLeft  = carsOnLeft > 0;
                    hasCarRight = carsOnRight > 0;
                }
                else if (hasCarLeft || hasCarRight)
                {
                    if (!channelLeftOpenTimerStarted)
                    {
                        timeWhenChannelShouldBeClosed = now.Add(timeToWaitBeforeClosingChannelLeftOpen);
                        channelLeftOpenTimerStarted   = true;
                    }
                    if (now > timeWhenChannelShouldBeClosed)
                    {
                        Console.WriteLine("Closing channel left open in spotter");
                        timeWhenChannelShouldBeClosed = DateTime.MaxValue;
                        hasCarLeft  = false;
                        hasCarRight = false;
                        audioPlayer.closeChannel();
                        channelLeftOpenTimerStarted = false;
                    }
                }
            }
        }