In this document, all remarkable changes are listed. Not mentioned are smaller code cleanups or documentation improvements.
- Nothing here yet...
- add
tracing
crate for logging support - breaking change:
Config::Input
must now satisfyDefault
+ serde'sSerialize
&DeserializeOwned
traits, rather than bytemuck'sPod
andZeroable
.- This allows enums with fields as well as variable-sized types (such as
Vec
) to be directly used as the GGRS input type, and should generally be more flexible than the old bounds. - To migrate old code, it's recommended to simply derive
Default
andSerialize
&Deserialize
on yourInput
type. - Or, to migrate old code strictly without changing behavior, implement
Default
in terms ofbytemuck::Zeroable::zeroed()
and implementSerialize
andDeserializedOwned
in terms ofbytemuck::bytes_of()
and (probably)bytemuck::pod_read_unaligned()
. - Fixes #40 and #74.
- This allows enums with fields as well as variable-sized types (such as
- lockstep determinism is now possible by setting max predictions to 0
- allow non-
Clone
types to be stored inGameStateCell
. - added
SyncTestSession::current_frame()
andSpectatorSession::current_frame()
to match the existingP2PSession::current_frame()
. - added
P2PSession::desync_detection()
to read the session's desync detection mode. - fix: ggrs no longer panics when a client's local frame advantage exceeds the range of an i8 (#35)
- fix: ggrs no longer panics when trying to send an overly large UDP packet, unless debug assertions are on.
- fix: ggrs no longer panics when trying to send a message over a custom socket implementation if that message exceeded the maximum safe UDP packet size, even though the underlying socket might have totally different applicable thresholds for what messages can be safely delivered.
- fix a false positive in
P2PSession
's desync detection; it was possible for a desync to incorrectly be detected whenP2PSession::advance_frame()
would 1. enqueue a checksum-changing rollback, 2. mark a to-be-rolled-back frame as confirmed, and 3. send that newly-confirmed frame's still-incorrect checksum to peers.
- fix dependency versions
- SyncTest now checks frames in chronological order
- Rename types with GGRS prefix to match rust naming conventions
- Removed deprecated
GgrsError
variants GameStateCell
now implements debug.- fixed a bug where checksums of unconfirmed frames were compared during desync detection.
- You can now trigger a desync manually in the example game by pressing SPACE.
SessionBuilder
now implements debug. This requiresConfig::Address
to have Debug- Optional desync detection for p2p sessions. This feature can be used by using
with_desync_detection_mode
in theSessionBuilder
.
- added support for fieldless enums in
PlayerInput
- fixed a bug where sync would not work with RTT higher than SYNC_RETRY_INTERVAL
- fixed multiple local players, added example documentation for it
- fixed save and advance request ordering during a rollback in P2PSessions
- removed
GameState
from the public API. - removed
PlayerInput
from the public API.AdvanceFrame
requests will now hand over a tuple with theInputStatus
and status of that input - added
InputStatus
enum to distinguish the status of given inputs - users now have to call
add_local_input(..)
for every local player before callingadvance_frame()
- enabled multiple players per endpoint
- sessions are now constructed through a unified
SessionBuilder
- overhauled all generics
- provided inputs are now generic. The user has to only supply a POD struct instead of serialized input
- added a
Config
trait with types to bundle all generic options - renamed
GameInput
toPlayerInput
- the user now has to explicitly create a socket themselves before creating a session
GameState
now is a genericGameState<T: Clone = Vec<u8>>
, so serialization of game state to save and load is no longer requiredtrait NonBlockingSocket
now is a genericNonBlockingSocket<A>
, whereA
generalizes the address that the socket uses to send a packet.
- massively improved performance by improving input packet handling
- added getter for the max prediction frames parameter in
P2PSession
andSyncTestSession
- removed the const
MAX_PREDICTION_FRAMES
and made it a parameter for the user to choose
- added
P2PSession::current_frame()
- made
P2PSession::confirmed_frame()
public to let users access it - removed the need for a player cap and a maximum input size
- adjusted session creation API to reflect the above change
- fixed a bug where a p2p session without remote players would not start
- migrated to rust 2021
- ggrs no longer panics when packets have been tampered with
- added
P2PSession::frames_ahead()
that shows how many frames the session believes to be ahead of other sessions.
- renamed session constructors to make them more idiomatic. Sessions are now created through
P2PSession::new(...)
andP2PSession::new_with_socket(...)
. - added functions to create sessions with own sockets provided
- turned NonBlockingSocket into a trait to allow alternate socket types in the future.
- fixed a bug where calling network_stats without any time passed would lead to a division by 0.
- fixed a bug where packet transmission time would be accounted for with RTT instead of RTT / 2
- fixed a bug where p2p sessions would falsely skip frames even when there able to run the frame
- implemented some first steps towards WASM compatibility
- changed license from MIT to MIT or Apache 2.0 at the users option
- added
local_player_handle()
toP2PSession
, which returns the handle of the local player - added
set_fps(desired_fps)
toP2PSpectatorSession
- users are now allowed to save
None
buffers for aGgrsRequest::SaveRequest
. This allows users to keep their own state history and load/save more efficiently - added
num_players()
,input_size()
getters to all sessions
- added sparse saving feature
P2PSession
, minimizing the SaveState requests to a bare minimum at the cost of potentially longer rollbacks - added
set_sparse_saving()
toP2PSession
to enable sparse saving - added
set_fps(desired_fps)
toP2PSession
for the user to set expected update frequency. This is helpful for frame synchronization between sessions - fixed a bug where a spectator would not handle disconnected players correctly with more than two players
- fixed a bug where changes to
disconnect_timeout
anddisconnect_notify_start
would change existings endpoints, but would not influence endpoints created afterwards - expanded the BoxGame example for up to four players and as many spectators as wanted
- minor code optimizations
- spectators catch up by advancing the frame twice per
advance_frame(...)
call, if too far behind - added
frames_behind_host()
toP2PSpectatorSession
, allowing to query how many frames the spectator client is behind the last received input - added
set_max_frames_behind(desired_value)
toP2PSpectatorSession
, allowing to set after how many frames behind the spectator fast-forwards to catch up - added
set_catchup_speed(desired_value)
toP2PSpectatorSession
, allowing to set how many frames the spectator catches up peradvance_frame()
call, if too far behind - in
SyncTestSession
, the user now can (and has to) provide input for all players in order to advance the frame
GgrsError::InvalidRequest
now has an addedinfo
field to explain the problem in more detail- removed unused
GgrsError::GeneralFailure
- removed multiple methods in
SyncTestSession
, as they didn't fulfill any meaningful purpose - removed unused sequence number from message header, fixing related issues
- fixed an issue where out-of-order packets would cause a crash
- other minor improvements
- when a player disconnects, the other players now rollback to that frame. This is done in order to eliminate wrong predictions and resimulate the game with correct disconnection indicators
- spectators now also handle those disconnections correctly
- fixed an issue where the spectator would assign wrong frames to the input
- players disconnecting now leads to a rollback to the disconnect frame, so wrongly made predictions can be removed
- in the box game example, disconnected players now spin
- minor code and documentation cleanups
- fixed an issue where encoding/decoding reference would not match, leading to client desyncs
- SyncTestSession now actually compares checksums again
- if the user doesn't provide checksums, GGRS computes a fletcher16 checksum
- internal refactoring/renaming
- fixed an issue where the spectator would only handle one UDP packet and drop the rest
- Reworked API: Instead of the user passing a GGRSInterface trait object, GGRS now returns a list of GgrsRequests for the user to fulfill