View previous topic :: View next topic |
Author |
Message |
NameZero912
Joined: 23 Jan 2009 Posts: 4
|
Posted: Fri Jan 23, 2009 8:43 am Post subject: Weird timing issues |
|
|
Hiho,
I've found out about a weird glitch in the DP engine, it is server-specific. Since I'm actually only a bit proficient at QuakeC (but not at C, and not at DarkPlaces code either) I'd just like to ask for your opinions what the cause for this glitch could be and whether/how it could be fixed
The time variable (of SSQC) does behave weird. Have a look at this screenshot. The first few lines show the normal output of time which I added into the SSQC code, so that time is printed each frame. In the first few lines it behaves as expected (slowmo is set to 1 at this point). But then, when I enter slowmo 0.001, things get weird. time does not continously increase anymore, but increases in steps. Also, the period at which the time value changes appears to be random. Furthermore, if you do something like self.nexthink = time + 0.0001 inside a Think-function of an entity, the value of self.nextthink is still time, and not time + 0.0001 !
Please note that what I just explained only happens if the server was running a map for a long time already. It can be simulated by disabling the timelimit and use slowmo 1000 for a few seconds. Set slowmo to 1 again, let the time be printed each frame and then set slowmo to 0.0001 (I tested this in Nexuiz SVN).
Thus, you won't experience this glitch if the server just loaded a new map, because in this case time will continously increase just fine.
The effect of this glitch appears in the Nexuiz sv_timeout feature which "pauses" the game by setting slowmo to 0.0001 - it goes to a point that the timeout feature is just broken (and the timeout is too short) once the map is running for a longer time due to the Think function which is called too often because the time value does not increase continously.
Kind regards,
NZ |
|
Back to top |
|
 |
Spike
Joined: 05 Nov 2004 Posts: 944 Location: UK
|
Posted: Fri Jan 23, 2009 11:29 am Post subject: |
|
|
quakec numeric types are limited to 32bit floats (or 3 32bit floats in the case of vectors).
single precision floats are not the most accurate, and with small increments (slowmo 0.0001) then the precision just isn't there.
Worse, when the time becomes really large, the precision for smaller increments is lost.
Internally, DarkPlaces uses doubles to represent floating point times. When these times are passed to QuakeC, they are rounded. And when they're rounded, the time value increases only every X frames, as there simply isn't the precision available to the data type.
Additionally, ftos rounds to 3 decimal points, thus will not give an accurate representation. I think. DP might be different.
Anyway, floating point precision degrades too much some time after about 2 days of up time (on the same map).
By using a really small slowmo value, you're increasing the required precision (reducing the value at which 'time' becomes intolerable), and having been 'up' for 2 and a half hours already, the precision just isn't there.
time + 0.0001 == time when time is sufficiently large that there is not enough precision.
As your screenshot shows, time increases periodically. Make it print the value of your nextthink too. You'll notice that that also increases periodically.
This is expected behaviour. _________________ What's a signature? |
|
Back to top |
|
 |
NameZero912
Joined: 23 Jan 2009 Posts: 4
|
Posted: Fri Jan 23, 2009 12:00 pm Post subject: |
|
|
Thanks for the hints. Divverent told me exactly the same.
Once I have more understanding of the engine code I'll have a look at the pause command of DP. I will try to modify it that it can be called from QC as well. All in good time  |
|
Back to top |
|
 |
NameZero912
Joined: 23 Jan 2009 Posts: 4
|
Posted: Fri Jan 23, 2009 1:50 pm Post subject: |
|
|
Gnah. I should have known it. DP won't execute any Think functions while the game is paused. To do the timeout feature I guess I'd have to do this:
- Keep the checks in SSQC, if checks are passed, call a new built-in function that sets sv.paused to 1 (e.g. TogglePause()) (there are many checks, e.g. if the one who calls it is a player, how many timeouts has he left, is there enough time for calling the timeout, the duration of the timeout, etc etc...)
- Additions to DP that track the amount of time X that passed from the moment where sv.paused was set, and to call a new, fixed QC function in the VM with X as parameter.
- This fixed QC function deals with unpausing the game again once X reached a specific value, by calling the TogglePause() built-in again |
|
Back to top |
|
 |
Spike
Joined: 05 Nov 2004 Posts: 944 Location: UK
|
Posted: Fri Jan 23, 2009 2:00 pm Post subject: |
|
|
FTE has a half-arsed flawed extension along these lines already.
ZQuake has a revised version which works much better.
Implement the zquake one.
I say this so we don't end up with too many conflicting extensions. _________________ What's a signature? |
|
Back to top |
|
 |
NameZero912
Joined: 23 Jan 2009 Posts: 4
|
Posted: Fri Jan 23, 2009 11:00 pm Post subject: |
|
|
Ok. I actually lack the time to do it now, but from what I can see ZQuake is doing this:
void PF_setpause (void) (built-in to be called by qc)
calls SV_TogglePause which sets sv.pausedstart = curtime;
Then there's GE_PausedTic() which, I suppose, is the function that has to be defined in QC. As parameter it gets this:
G_FLOAT(OFS_PARM0) = curtime - sv.pausedstart;
Then there is also void SV_CheckTimeouts (void) which checks for clients that timed out. When there are no clients left on the server it asks GE_ShouldPause(), a QC function, which can return a boolean to indicate whether it wants the game to still be paused even though there are no clients left (returning true) or allow the server to unpause it (returning false).
The reason for my hesitation to implement this right away is
a) I am not familiar with how built-ins are defined, and not how the functions that will be implemented in QC but called by the engine (is there a name for them?) are defined, either
b) exams are due  |
|
Back to top |
|
 |
Spike
Joined: 05 Nov 2004 Posts: 944 Location: UK
|
Posted: Sat Jan 24, 2009 2:21 am Post subject: |
|
|
I think there's an EndFrame tutorial somewhere around which would show you how to call a QC function from an lightly modded engine.
Presumably there are a few tutorials that demonstrate the code required to add a builtin, too.
Builtins are fairly easy really. There's a table somewhere in the engine that contains function pointers, one for each builtin slot. And the relative one is called.
Regarding calling a QC function from the engine - the hard part is finding its number. There are many examples of calling think/touch/blocked/etc functions throughout the server's code. But yeah, finding which function to use is a little more tricky, as a lightly modded engine likely has no such existing examples. _________________ What's a signature? |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2004 phpBB Group
|