Skip to content

Conversation

@xSL0W
Copy link

@xSL0W xSL0W commented Jun 30, 2025

Steps to reproduce this bug:

  • Use a lib.progressbar longer than 60-90s and will guarantee to fail most of the time
    I found this while testing my crafting system which uses a very long progressbar (300 seconds) and most of the time was failing. I initially though it was my crafting system but digging deeply this part was failing in oxlib:
if progress == false or duration <= data.duration then

I believe the issue is a time desync between NUI and GetGameTimer(), initially Linden/Luke gave a +100ms slight compensation which was only good for short time "errors", not for longer ones.
This might be a temporary solution only. A better one to compensate the error fully might be better.

@unitysync
Copy link

@xSL0W Can you provide video repro pls?

@xSL0W
Copy link
Author

xSL0W commented Jul 10, 2025

Just create a lib.progress for 300s and will 100% return false most of the time.

@adamdrakon
Copy link

Can confirm this issue exists. Started encountering it repeatedly for the first time today (granted I had not been using a version of ox_lib with the duration check until a couple of days ago).
Seems more prominent if client's PC is having performance issues.

@xSL0W
Copy link
Author

xSL0W commented Aug 27, 2025

Seems more prominent if client's PC is having performance issues.

Found this yesterday too. A player with ~20FPS would not be able to complete the progressbar.

What if we use GetNetworkTimeAccurate() instead of GetGameTimer() ? This one is calculated by the server, not the client, could be more accurate.

@xSL0W
Copy link
Author

xSL0W commented Aug 27, 2025

I made a small testing code and using GetNetworkTimeAccurate() with the dynamic offset seems to work just fine. Haven't tested with low fps.

for i = 45, 50 do
    if lib.progressBar({
            duration = i * 10 * 1000,
            label = 'Testing ' .. i .. ' with duration ' .. (i * 10) .. 's',
            useWhileDead = false,
            canCancel = true,
            disable = {
                car = true,
            },
        }) then
        print('(OK) Iteration i = ' .. i .. ' with duration of ' .. (i * 10) .. 's SUCCEEDED')
    else
        print('(ERROR) Iteration i = ' .. i .. ' with duration of ' .. (i * 10) .. 's FAILED')
    end
end

After testing:
(OK) Iteration i = 45 with duration of 450s SUCCEEDED
(OK) Iteration i = 46 with duration of 460s SUCCEEDED
(OK) Iteration i = 47 with duration of 470s SUCCEEDED
(OK) Iteration i = 48 with duration of 480s SUCCEEDED
(OK) Iteration i = 49 with duration of 490s SUCCEEDED
(OK) Iteration i = 50 with duration of 500s SUCCEEDED

@adamdrakon
Copy link

I made a small testing code and using GetNetworkTimeAccurate() with the dynamic offset seems to work just fine. Haven't tested with low fps.

for i = 45, 50 do
    if lib.progressBar({
            duration = i * 10 * 1000,
            label = 'Testing ' .. i .. ' with duration ' .. (i * 10) .. 's',
            useWhileDead = false,
            canCancel = true,
            disable = {
                car = true,
            },
        }) then
        print('(OK) Iteration i = ' .. i .. ' with duration of ' .. (i * 10) .. 's SUCCEEDED')
    else
        print('(ERROR) Iteration i = ' .. i .. ' with duration of ' .. (i * 10) .. 's FAILED')
    end
end

After testing: (OK) Iteration i = 45 with duration of 450s SUCCEEDED (OK) Iteration i = 46 with duration of 460s SUCCEEDED (OK) Iteration i = 47 with duration of 470s SUCCEEDED (OK) Iteration i = 48 with duration of 480s SUCCEEDED (OK) Iteration i = 49 with duration of 490s SUCCEEDED (OK) Iteration i = 50 with duration of 500s SUCCEEDED

I'll give it a test on my end shortly, I can reliably reproduce the performance issue I was having so I can get a good feel for how effective the solution is.

@adamdrakon
Copy link

Certainly seems to effectively address the issue, at least for me. With or without the use of GetNetworkTimeAccurate().
My performance isn't as tanked today as it was last time I was testing, but I'm not encountering the issue anymore.

May be worth implementing.

@Maximus7474
Copy link

Maximus7474 commented Sep 1, 2025

So your solution is providing a 20% buffer if I understand correctly ?

It seems a bit exagerated, as on my tests I'm getting a difference of below 1%:

set duration (ms) calculated duration (ms) difference
100 000 580 0.58%
200 000 807 0.40%
300 000 824 0.27%
400 000 2741 0.69% (PC hitched during the test)

Don't know by how much this would vary on lower spec PCs, and I couldn't be bothered running more iterations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants