@@ -152,6 +152,9 @@ void TasPlayer::Activate(TasPlaybackInfo info) {
152152
153153 for (int slot = 0 ; slot < 2 ; ++slot) {
154154 playbackInfo.slots [slot].ClearGeneratedContent ();
155+
156+ currentInputFramebulkIndex[slot] = 0 ;
157+ currentToolsFramebulkIndex[slot] = 0 ;
155158 }
156159
157160 active = true ;
@@ -303,16 +306,50 @@ void TasPlayer::AdvanceFrame() {
303306
304307// returns raw framebulk that should be used for given tick
305308TasFramebulk TasPlayer::GetRawFramebulkAt (int slot, int tick) {
306- int closestTime = INT_MAX;
307- TasFramebulk closest;
308- for (TasFramebulk framebulk : playbackInfo.slots [slot].framebulks ) {
309- int timeDist = tick - framebulk.tick ;
310- if (timeDist >= 0 && timeDist < closestTime) {
311- closestTime = timeDist;
312- closest = framebulk;
309+ // Do binary search for bulks immediately before and after our target tick
310+ uint32_t before = 0 ;
311+ uint32_t after = playbackInfo.slots [slot].framebulks .size () - 1 ;
312+
313+ if (playbackInfo.slots [slot].framebulks [before].tick == tick) {
314+ return playbackInfo.slots [slot].framebulks [before];
315+ }
316+ if (playbackInfo.slots [slot].framebulks [after].tick == tick) {
317+ return playbackInfo.slots [slot].framebulks [after];
318+ }
319+
320+ while (before + 1 != after) {
321+ uint32_t middle = (before + after) / 2 ;
322+ TasFramebulk middle_bulk = playbackInfo.slots [slot].framebulks [middle];
323+
324+ if (middle_bulk.tick < tick) {
325+ before = middle;
326+ } else if (middle_bulk.tick > tick) {
327+ after = middle;
328+ } else {
329+ return middle_bulk;
313330 }
314331 }
315- return closest;
332+
333+ return playbackInfo.slots [slot].framebulks [before];
334+ }
335+
336+ // returns raw framebulk using more efficient method with cached incremented index of last used tick
337+ TasFramebulk TasPlayer::GetRawFramebulkAt (int slot, int tick, int & cachedIndex) {
338+ if (cachedIndex < 0 ) {
339+ cachedIndex = 0 ;
340+ }
341+
342+ auto maxIndex = playbackInfo.slots [slot].framebulks .size () - 1 ;
343+
344+ if (cachedIndex >= maxIndex) {
345+ return playbackInfo.slots [slot].framebulks [maxIndex];
346+ }
347+
348+ while (cachedIndex < maxIndex && playbackInfo.slots [slot].framebulks [cachedIndex + 1 ].tick <= tick) {
349+ cachedIndex++;
350+ }
351+
352+ return playbackInfo.slots [slot].framebulks [cachedIndex];
316353}
317354
318355TasPlayerInfo TasPlayer::GetPlayerInfo (int slot, void *player, CUserCmd *cmd, bool clientside) {
@@ -494,7 +531,7 @@ void TasPlayer::FetchInputs(int slot, TasController *controller) {
494531 // to actually hook at _Host_RunFrame_Input or CL_Move.
495532 int tick = currentTick + 1 ;
496533
497- TasFramebulk fb = GetRawFramebulkAt (slot, tick);
534+ TasFramebulk fb = GetRawFramebulkAt (slot, tick, currentInputFramebulkIndex[slot] );
498535
499536 int fbTick = fb.tick ;
500537
@@ -563,7 +600,7 @@ void TasPlayer::PostProcess(int slot, void *player, CUserCmd *cmd) {
563600 return ;
564601 }
565602
566- TasFramebulk fb = GetRawFramebulkAt (slot, tasTick);
603+ TasFramebulk fb = GetRawFramebulkAt (slot, tasTick, currentToolsFramebulkIndex[slot] );
567604
568605 // update all tools that needs to be updated
569606 auto fbTick = fb.tick ;
0 commit comments