Add replay validation

This commit is contained in:
Miloslav Ciz 2025-06-11 22:25:29 +02:00
parent f0d8521e90
commit 57097c57bb
3 changed files with 78 additions and 20 deletions

View file

@ -168,10 +168,9 @@ struct
uint16_t crashState;
uint8_t playingReplay;
struct
{
uint8_t on; ///< Currently playing replay?
uint16_t eventCount;
uint16_t events[LCR_SETTING_REPLAY_MAX_SIZE];
@ -376,7 +375,7 @@ int LCR_replayHasFinished(void)
for (int i = 0; i < LCR_racing.replay.eventCount; ++i)
totalTime += LCR_racing.replay.events[i] >> 4;
return totalTime >= LCR_racing.replay.achievedTime;
return totalTime > LCR_racing.replay.achievedTime;
}
return LCR_racing.replay.currentEvent > LCR_racing.replay.eventCount;
@ -445,7 +444,8 @@ int LCR_replayRecordEvent(uint32_t frame, uint8_t input)
frame -= previousFrame; // convert to offset
while (frame > 4095 && LCR_racing.replay.eventCount < LCR_SETTING_REPLAY_MAX_SIZE)
while (frame > 4095 && LCR_racing.replay.eventCount <
LCR_SETTING_REPLAY_MAX_SIZE)
{
// add intermediate events
frame -= 4095;
@ -982,7 +982,7 @@ void LCR_racingRestart(uint8_t replay)
LCR_racing.tick = 0;
LCR_racing.fanForce = 0;
LCR_racing.playingReplay = replay;
LCR_racing.replay.on = replay;
TPE_bodyActivate(&(LCR_racing.carBody));
LCR_racing.wheelCollisions = 0;
@ -1066,7 +1066,7 @@ void LCR_racingInit(void)
TPE_worldInit(&(LCR_racing.physicsWorld),
&(LCR_racing.carBody),1,_LCR_racingEnvironmentFunction);
LCR_racing.playingReplay = 0;
LCR_racing.replay.on = 0;
LCR_racing.physicsWorld.collisionCallback = _LCR_racingCollisionHandler;
}
@ -1217,7 +1217,7 @@ uint32_t LCR_racingStep(unsigned int input)
LCR_racing.groundMaterial = LCR_BLOCK_MATERIAL_CONCRETE;
if (LCR_racing.playingReplay)
if (LCR_racing.replay.on)
{
if (LCR_racing.tick == 0)
LCR_replayInitPlaying();
@ -1637,7 +1637,7 @@ uint32_t LCR_racingStep(unsigned int input)
{
result |= LCR_RACING_EVENT_FINISHED;
if (!LCR_racing.playingReplay)
if (!LCR_racing.replay.on)
LCR_replayRecordEvent(LCR_racing.tick,LCR_REPLAY_EVENT_END);
}
}
@ -1677,5 +1677,63 @@ void LCR_physicsDebugDraw(LCR_GameUnit camPos[3], LCR_GameUnit camRot[2],
cPos,cRot,cView,16,LCR_PHYSICS_UNIT / 4,LCR_racing.tick * 4);
#endif
}
/**
Validates replay, i.e. checks if it finishes and whether its achieved time
agrees with the stored time. The function can only be called when both the
replay and the correct map are loaded. The loaded replay's playing position
will be reset after this function returns.
*/
int LCR_replayValidate(void)
{
LCR_LOG1("validating replay");
int result = 0;
LCR_racingRestart(1);
while (LCR_racing.tick < 0x00f00000 // no infinite loops
&& LCR_racing.tick <= LCR_racing.replay.achievedTime)
{
int coords[3];
LCR_racingStep(0);
LCR_racingGetCarBlockCoords(coords);
coords[0] = LCR_mapGetBlockAt(coords[0],coords[1],coords[2]);
if (coords[0] && LCR_currentMap.blocks[coords[0] * LCR_BLOCK_SIZE] ==
LCR_BLOCK_FINISH)
{
uint8_t allCPsTaken = 1; // reuse as variable
for (int i = 0; i < LCR_currentMap.blockCount; ++i)
if (LCR_currentMap.blocks[i * LCR_BLOCK_SIZE] == LCR_BLOCK_CHECKPOINT_0)
{
allCPsTaken = 0;
break;
}
if (allCPsTaken)
{
result = LCR_racing.tick == (LCR_racing.replay.achievedTime + 1);
break;
}
}
}
if (result)
{
LCR_LOG1("replay valid");
}
else
{
LCR_LOG1("replay invalid!");
}
LCR_racingRestart(1);
return result;
}
#endif // guard