You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It turns out game.time() wraps around to 0 after ~30¼ game days ((2³² - 1) - 1,679,936,192 game milliseconds). One option would be to convert the C++ struct returned by game.get_game_time() into seconds and use that in place of game.time() wherever sub-second precision is not required. The Lua built-in os.time function could be used for the conversion, albeit at the cost of sub-second rounding errors. Here is an example of how to implement that: 9919135. If millisecond precision were required, get_game_time_in_seconds() in the aforementioned commit could be modified to return a fractional os.time(time_table) + ms * 0.001, however saving it without losing precision might be tricky since the engine doesn't expose a double-precision floating point save method.
Saving a large u32 — like that returned by get_game_time_in_seconds() in the commit above, assuming not modified for fractional precision — as a float32 is a bad idea; we begin losing precision with odd numbers above 16,777,216 (2²⁴) and even numbers above 33,554,432 (2²⁵). That means we can only save up to ~194.18 days of seconds into a float32 before we begin seeing ±1 second rounding errors. Past ~388.36 days, these grow to ±2 seconds. If counting were to begin from the epoch (as in os.time), we'd already be way over the precision limit when the game starts at 06:10 2011/09/10, and our rounding errors would be immense (±64 seconds). Even if counting began from 2011/01/01 instead, we'd be up to 21,795,000 seconds when the game starts. We could hard-code the counting to begin at the vanilla game start time, but that could break mods that use a different start time. As there seems to be no way to access the game start time directly from Lua, my solution against game.time() precision loss in f4b5ce8 was to detect fractional numbers in xr_logic.pstor_save_all and save those as float32, else save as s32 or u32 yielding 2,147,483,647 (2³¹ - 1) or 4,294,967,295 (2³² - 1) seconds of wiggle room, respectively.
To save a fractional get_game_time_in_seconds() without precision loss would likely require saving the fractional part separately, perhaps as a u16.
The text was updated successfully, but these errors were encountered:
Another quirk of vanilla X-Ray seems to be that the precision of integers >= 2³¹ saved as u32 is limited to the nearest multiple of 256. So, any integers >= 2,147,483,648 will be rounded to the nearest multiple of 256 when saved using e.g. xr_logic.pstor_save_all. Thus, if the number saved is in milliseconds, then the number loaded would have a rounding error of up to 128 milliseconds. No big deal if we only need to-the-nearest-second precision, but suppose we're saving a number denominated in seconds. We'd have a rounding error of over 2 minutes in the worst-case scenario!
It turns out
game.time()
wraps around to 0 after ~30¼ game days ((2³² - 1) - 1,679,936,192 game milliseconds). One option would be to convert the C++ struct returned bygame.get_game_time()
into seconds and use that in place ofgame.time()
wherever sub-second precision is not required. The Lua built-inos.time
function could be used for the conversion, albeit at the cost of sub-second rounding errors. Here is an example of how to implement that: 9919135. If millisecond precision were required,get_game_time_in_seconds()
in the aforementioned commit could be modified to return a fractionalos.time(time_table) + ms * 0.001
, however saving it without losing precision might be tricky since the engine doesn't expose a double-precision floating point save method.Saving a large u32 — like that returned by
get_game_time_in_seconds()
in the commit above, assuming not modified for fractional precision — as a float32 is a bad idea; we begin losing precision with odd numbers above 16,777,216 (2²⁴) and even numbers above 33,554,432 (2²⁵). That means we can only save up to ~194.18 days of seconds into a float32 before we begin seeing ±1 second rounding errors. Past ~388.36 days, these grow to ±2 seconds. If counting were to begin from the epoch (as inos.time
), we'd already be way over the precision limit when the game starts at 06:10 2011/09/10, and our rounding errors would be immense (±64 seconds). Even if counting began from 2011/01/01 instead, we'd be up to 21,795,000 seconds when the game starts. We could hard-code the counting to begin at the vanilla game start time, but that could break mods that use a different start time. As there seems to be no way to access the game start time directly from Lua, my solution againstgame.time()
precision loss in f4b5ce8 was to detect fractional numbers inxr_logic.pstor_save_all
and save those as float32, else save as s32 or u32 yielding 2,147,483,647 (2³¹ - 1) or 4,294,967,295 (2³² - 1) seconds of wiggle room, respectively.To save a fractional
get_game_time_in_seconds()
without precision loss would likely require saving the fractional part separately, perhaps as a u16.The text was updated successfully, but these errors were encountered: