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); }
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); } }
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); } }
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); } } } }
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; } } } }