Struct crystalorb::Config[][src]

pub struct Config {
    pub lag_compensation_latency: f64,
    pub blend_latency: f64,
    pub timestep_seconds: f64,
    pub clock_sync_needed_sample_count: usize,
    pub clock_sync_assumed_outlier_rate: f64,
    pub clock_sync_request_period: f64,
    pub max_tolerable_clock_deviation: f64,
    pub snapshot_send_period: f64,
    pub update_delta_seconds_max: f64,
    pub timestamp_skip_threshold_seconds: f64,
    pub fastforward_max_per_step: usize,
    pub tweening_method: TweeningMethod,
}
Expand description

Configuration parameters that tweak how CrystalOrb works.

For starters, you can just pass in the default values when you are creating the client::Client and server::Server instances.

Example

use crystalorb::{Config, client::Client};
use crystalorb_demo::DemoWorld;

let client = Client::<DemoWorld>::new(Config::new());

Fields

lag_compensation_latency: f64

Maximum amount of client lag in seconds that the server will compensate for. A higher number allows a client with a high ping to be able to perform actions on the world at the correct time from the client’s point of view. The server will only simulate lag_compensation_latency seconds in the past, and let each client predict lag_compensation_latency seconds ahead of the server using the command buffers.

blend_latency: f64

When a client receives a snapshot update of the entire world from the server, the client uses this snapshot to update their simulation. However, immediately displaying the result of this update will have entities suddenly teleporting to their new destinations. Instead, we keep simulating the world without the new snapshot information, and slowly blend into the world with the new snapshot information. We linearly interpolate from the old and new worlds, taking blend_latency seconds before the user sees the entities in their updated locations.

timestep_seconds: f64

The number of seconds that gets simulated with every World step. This is the physics simulation “dt”. This can be different to the delta_seconds between each Client::update/Server::update call. For more accurate and predictable physics simulations, you may want to have a smaller timestep_seconds. If your physics simulation is computationally intensive, you may want to have a larger timestep_seconds.

clock_sync_needed_sample_count: usize

The number of of clock sync responses from the server before the client averages them to update the client’s clock. The higher this number, the more resilient it is to jitter, but the longer it takes before the client becomes ready.

clock_sync_assumed_outlier_rate: f64

The assumed probability that the next clock_sync response sample is an outlier. Before the samples are averaged, outliers are ignored from the calculation. The number of samples to ignore is determined by this numebr, with a minimum of one sample ignored from each extreme (i.e. the max and the min sample gets ignored).

clock_sync_request_period: f64

This determines how rapid the client sends clock_sync requests to the server, represented as the number of seconds before sending the next request.

max_tolerable_clock_deviation: f64

How big the difference needs to be between the following two:

  1. the server clock offset value that the client is currently using for its calculations, compared with
  2. the current rolling average server clock offset that was measured using clock_sync messages, before updating the clients.
snapshot_send_period: f64

How many seconds to wait before the server sends another snapshot out to the clients. The smaller this number, the higher the network traffic, but the sooner the client gets to correctly apply other clients’ commands at the correct timestmp. Regarding the latter point, this is because commands take time to travel between clients, and by the time a client receives another client’s command, the command’s intended timestamp would have already been passed. The client can’t rewind the world to reapply the command at the intended timestamp, so the best thing it can do is to apply at the current timestamp, and wait until the next server snapshot before finally applying the command at the intended timestamp during the snapshot fastforwarding process.

update_delta_seconds_max: f64

This is the limit that CrystalOrb enforces to limit the number of times that the World’s step function gets called per rendering frame (i.e. per Client::update or Server::update). This is to prevent a catastrophic situation where CrystalOrb could not keep up in one rendering frame, and making it worse in the next frame, and subsequently “freezing” up in a positive feedback loop.

timestamp_skip_threshold_seconds: f64

Due to floating-point rounding errors and due to the update_delta_seconds_max limit that CrystalOrb enforces, the simulation Timestamp might slowly drift away from the intended value according to the system clock (which is a way to make sure that different clients on different machines stay in sync in terms of time). When this time drift is small, CrystalOrb can compensate it in the next update by running extra simulation frames or some fewer frames than usual. However, if the timestamp drift becomes too large, it is not possible to correct all of this drift in one update using this method, and instead we need to perform a “time-skip” without running the corresponding simulation steps. The threshold for this drift before we start skipping some simulation frames is defined by this configuration parameter.

Large timestamp drifts could happen when, for example, the game client has some system lag. If the game client is hosted in the web browser, for exmple, then large timestamp drifts can occur when the browser tab goes out of focus and sleeps. Large timestamp drifts can also occur on the laptop when the computer enters sleep mode, etc.

fastforward_max_per_step: usize

When the Client receives a Snapshot from the Server, the snapshot is going to have a timestamp older than the current client simulation timestamp. Before the snapshot can be blended into the client, it needs to fastforwarded to the current timestamp by running more simulation frmes on the snapshot than on the world that is currently displayed on the client. This configuration parameter specifies how much faster the snapshot can be simulated compared with the existing client world during the fastforwarding process. A value of 2, for example, would represent that the received server snapshot could only run at most 2 simulation steps every time the existing client world runs one step. In this scenario, if the server snapshot is 10 frames behind the client, then it would take 10 client frames before the server snapshot ctches up with the client.

tweening_method: TweeningMethod

In crystalorb, the physics simulation is assumed to be running at a fixed timestep that is different to the rendering refresh rate. To suppress some forms of temporal aliasing due to these different timesteps, crystalorb allows the interpolate between the simulated physics frames to derive the displayed state.

Implementations

Returns a set of useable default configuration parameters.

Examples

If you want to use the defaults:

use crystalorb::{Config, client::Client};
use crystalorb_demo::DemoWorld;

let client = Client::<DemoWorld>::new(Config::new());

If you want to override the defaults:

use crystalorb::{Config, client::Client};
use crystalorb_demo::DemoWorld;
let client = Client::<DemoWorld>::new(Config {
    lag_compensation_latency: 0.5,
    ..Config::new()
});

You can use Default::default() too:

use crystalorb::{Config, client::Client};
use crystalorb_demo::DemoWorld;
let client = Client::<DemoWorld>::new(Config {
    lag_compensation_latency: 0.5,
    ..Default::default()
});

Note that this is a constant function, so you can initialize your configuration as a constant.

use crystalorb::Config;
const CONFIG: Config = Config {
    timestep_seconds: 1.0 / 24.0,
    ..Config::new()
};

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Returns the “default value” for a type. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

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

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

Performs the conversion.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

Uses borrowed data to replace owned data, usually by cloning. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

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

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