Skip to main content

Lockstep

Struct Lockstep 

Source
pub struct Lockstep { /* private fields */ }
Expand description

Transport-agnostic lockstep state machine for one peer.

Implementations§

Source§

impl Lockstep

Source

pub fn new(local: PlayerId, players: Vec<PlayerId>, delay: u32) -> Lockstep

Source

pub fn observer(players: Vec<PlayerId>, delay: u32) -> Lockstep

A session that watches: it receives every player’s input and simulates the same frames, but commits nothing and is waited for by nobody. A spectator falling behind is a spectator’s problem.

Source

pub fn request_pause(&mut self) -> u32

Call a pause. Returns the frame the session will freeze on, to be broadcast to the peers; a pause already in flight wins if it lands earlier, so two players hitting Escape together agree.

Source

pub fn receive_pause(&mut self, frame: u32)

A peer called a pause at frame. The earliest proposal wins, so every peer converges on one frame however the messages interleave.

Two kinds of Pause are not proposals and are dropped: one naming a frame this peer has already simulated (every player committed past it, so nobody is stopping there), and one naming a pause that has since been lifted (see lifted). Both are the per-tick echoes of a pause that is over, arriving after the resume.

Source

pub fn resume(&mut self) -> u32

Lift the pause and let commits flow again. Safe to call unpaused. Returns the frame the lifted pause was to freeze on (the highest ever lifted here, if there was no pause to lift), for the peers.

Source

pub fn receive_resume(&mut self, frame: u32) -> u32

A peer lifted the pause that was to freeze on frame. Whatever pause is in flight here is lifted with it: the peers agree on one frame, and a peer that had not yet heard the earliest proposal is resuming from the same pause under a later number.

Source

pub fn pause_frame(&self) -> Option<u32>

The frame this session is frozen on, if paused.

Source

pub fn lifted_pause(&self) -> Option<u32>

The frame of the pause most recently lifted, if any ever was: what a repeated Resume names.

Source

pub fn paused(&self) -> bool

Whether a pause has been called (the freeze itself lands a beat later, when the simulated frame reaches Lockstep::pause_frame).

Source

pub fn frozen(&self) -> bool

Whether the sim has actually come to rest on the pause frame: the moment the picture on screen stops moving.

Source

pub fn commit_local(&mut self, action: PlayerAction) -> Option<InputMsg>

Commit the local action for the next input frame; returns the message to send to every peer, or None if the sim has fallen too far behind (a stalled peer) or the session is paused. The caller should retry the action next frame rather than let commits run unboundedly ahead.

Source

pub fn recent_commits(&self) -> &[InputMsg]

The recent local commits, oldest first: every one a peer still in step with us could be missing (see [resend_span]). Resend these every step so packet loss (or a not-yet-completed handshake) cannot stall the peer.

Source

pub fn awaiting(&self) -> Vec<PlayerId>

Which players the next frame is still waiting on. Empty means it is ready to simulate; anything else is who everybody is held up by.

Read-only, because the shell asks this to put a name on screen while the picture is still, and a question the HUD asks every frame must not be one that writes. Only seated players can hold a frame up; an absent seat is filled at the moment its frame is made.

Source

pub fn abandon(&mut self, player: PlayerId, frame: u32)

Give up on a player who has stopped sending, from frame on.

Every frame from there fills their slot the way an absent seat is filled, including the frames already waiting on it, which unsticks the round in the same breath. What moves into the empty chair is not this layer’s business: the shell puts an AI there, and every peer derives the same moves for it from the same board.

The frame is the one the decider was held up on, and it travels with the decision, because the peers do not all hold the same inputs from a player who has gone quiet: the host relays each input as it arrives, and a peer that missed the relay of frame n may well hold n + 2. Filling only the empty slots had that peer play n + 2 as sent while the host, which never got n and stopped there, played it empty. Every slot from frame on is emptied instead, whatever it held, and every peer applies the same frame. A peer cannot have simulated past frame already: the decider had no input for it, and no peer hears from a player except through the decider.

Source

pub fn receive(&mut self, msg: InputMsg)

Feed a peer’s message (duplicates and already-simulated frames are ignored, so resends are harmless).

A frame further ahead than any peer still in step could have committed is ignored too: their commits run at most a lead past their frame, and their frame at most a lead past ours (see [resend_span]). Every frame accepted here makes a slot, and a peer naming frames up to u32::MAX would otherwise grow the table without bound.

Source

pub fn advance(&mut self) -> Option<[PlayerAction; 6]>

If every player’s action for the next frame is known, pop it for simulation. None means “stall this render frame”: never guess.

Source

pub fn frame(&self) -> u32

Source

pub fn watching(&self) -> bool

Whether this peer is watching rather than playing.

Source

pub fn seat(&self) -> Option<PlayerId>

The seat this peer plays, if it plays one.

Source

pub fn player_count(&self) -> usize

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

Source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoResult<T> for T

Source§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
Source§

impl<A> Is for A
where A: Any,

Source§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Settings for T
where T: 'static + Send + Sync,

Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more