Skip to content

Commit

Permalink
Use dedicated resource for server tick
Browse files Browse the repository at this point in the history
  • Loading branch information
Shatur committed Oct 3, 2023
1 parent ff851fc commit f89c79f
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 75 deletions.
10 changes: 4 additions & 6 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ use bevy_renet::{renet::Bytes, transport::client_connected};
use bevy_renet::{renet::RenetClient, transport::NetcodeClientPlugin, RenetClientPlugin};
use bincode::{DefaultOptions, Options};

use crate::{
replicon_core::{
replication_rules::{Mapper, Replication, ReplicationRules},
REPLICATION_CHANNEL_ID,
},
server::RepliconTick,
use crate::replicon_core::{
replication_rules::{Mapper, Replication, ReplicationRules},
replicon_tick::RepliconTick,
REPLICATION_CHANNEL_ID,
};

pub struct ClientPlugin;
Expand Down
9 changes: 5 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,12 @@ will be replicated.
If you need to disable replication for specific component for specific entity,
you can insert [`Ignored<T>`] component and replication will be skipped for `T`.
### [`RepliconTick`], and fixed timestep games.
### Tick and fixed timestep games
The [`ServerPlugin`] sends replication data in `PostUpdate` any time the [`RepliconTick`] resource
The [`ServerPlugin`] sends replication data in `PostUpdate` any time the [`ServerTick`] resource
changes. By default, its incremented in `PostUpdate` per the [`TickPolicy`].
If you set [`TickPolicy::Manual`], you can increment [`RepliconTick`] at the start of your
If you set [`TickPolicy::Manual`], you can increment [`ServerTick`] at the start of your
`FixedTimestep` game loop. This value can represent your simulation step, and is made available
to the client in the custom deserialization, despawn and component removal functions.
Expand Down Expand Up @@ -396,10 +396,11 @@ pub mod prelude {
AppReplicationExt, Ignored, MapNetworkEntities, Mapper, Replication,
ReplicationRules,
},
replicon_tick::RepliconTick,
NetworkChannels, RepliconCorePlugin,
},
server::{
has_authority, AckedTicks, RepliconTick, ServerPlugin, ServerSet, TickPolicy, SERVER_ID,
has_authority, AckedTicks, ServerPlugin, ServerSet, ServerTick, TickPolicy, SERVER_ID,
},
ReplicationPlugins,
};
Expand Down
1 change: 1 addition & 0 deletions src/replicon_core.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod replication_rules;
pub mod replicon_tick;

use bevy::prelude::*;
use bevy_renet::renet::{ChannelConfig, SendType};
Expand Down
6 changes: 2 additions & 4 deletions src/replicon_core/replication_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ use bevy_renet::renet::Bytes;
use bincode::{DefaultOptions, Options};
use serde::{de::DeserializeOwned, Deserialize, Serialize};

use crate::{
client::{ClientMapper, NetworkEntityMap},
server::RepliconTick,
};
use super::replicon_tick::RepliconTick;
use crate::client::{ClientMapper, NetworkEntityMap};

pub trait AppReplicationExt {
/// Marks component for replication.
Expand Down
52 changes: 52 additions & 0 deletions src/replicon_core/replicon_tick.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::cmp::Ordering;

use serde::{Deserialize, Serialize};

/// Wraps a value that represents an index of server update.
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct RepliconTick(pub(crate) u32);

impl RepliconTick {
/// Gets the value of this tick.
#[inline]
pub fn get(self) -> u32 {
self.0
}

/// Increments current tick by the specified `value` and takes wrapping into account.
#[inline]
pub fn increment_by(&mut self, value: u32) {
self.0 = self.0.wrapping_add(value);
}

/// Same as [`Self::increment_by`], but increments only by 1.
#[inline]
pub fn increment(&mut self) {
self.increment_by(1)
}
}

impl PartialOrd for RepliconTick {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let difference = self.0.wrapping_sub(other.0);
if difference == 0 {
Some(Ordering::Equal)
} else if difference > u32::MAX / 2 {
Some(Ordering::Less)
} else {
Some(Ordering::Greater)
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn tick_comparsion() {
assert_eq!(RepliconTick(0), RepliconTick(0));
assert!(RepliconTick(0) < RepliconTick(1));
assert!(RepliconTick(0) > RepliconTick(u32::MAX));
}
}
77 changes: 16 additions & 61 deletions src/server.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub(super) mod despawn_tracker;
pub(super) mod removal_tracker;

use std::{cmp::Ordering, io::Cursor, mem, time::Duration};
use std::{io::Cursor, mem, time::Duration};

use bevy::{
ecs::{
Expand All @@ -21,10 +21,10 @@ use bevy_renet::{
RenetServerPlugin,
};
use bincode::{DefaultOptions, Options};
use serde::{Deserialize, Serialize};

use crate::replicon_core::{
replication_rules::{ReplicationId, ReplicationInfo, ReplicationRules},
replicon_tick::RepliconTick,
REPLICATION_CHANNEL_ID,
};
use despawn_tracker::{DespawnTracker, DespawnTrackerPlugin};
Expand Down Expand Up @@ -53,7 +53,7 @@ impl Plugin for ServerPlugin {
DespawnTrackerPlugin,
))
.init_resource::<AckedTicks>()
.init_resource::<RepliconTick>()
.init_resource::<ServerTick>()
.configure_set(
PreUpdate,
ServerSet::Receive.after(NetcodeServerPlugin::update_system),
Expand All @@ -62,7 +62,7 @@ impl Plugin for ServerPlugin {
PostUpdate,
ServerSet::Send
.before(NetcodeServerPlugin::send_packets)
.run_if(resource_changed::<RepliconTick>()),
.run_if(resource_changed::<ServerTick>()),
)
.add_systems(
PreUpdate,
Expand Down Expand Up @@ -108,8 +108,8 @@ impl ServerPlugin {
}

/// Increments current server tick which causes the server to send a diff packet this frame.
pub fn increment_tick(mut replicon_tick: ResMut<RepliconTick>) {
replicon_tick.increment();
pub fn increment_tick(mut server_tick: ResMut<ServerTick>) {
server_tick.increment();
}

fn acks_receiving_system(mut acked_ticks: ResMut<AckedTicks>, mut server: ResMut<RenetServer>) {
Expand Down Expand Up @@ -152,13 +152,13 @@ impl ServerPlugin {
mut set: ParamSet<(&World, ResMut<RenetServer>, ResMut<AckedTicks>)>,
replication_rules: Res<ReplicationRules>,
despawn_tracker: Res<DespawnTracker>,
replicon_tick: Res<RepliconTick>,
server_tick: Res<ServerTick>,
removal_trackers: Query<(Entity, &RemovalTracker)>,
) -> Result<(), bincode::Error> {
let mut acked_ticks = set.p2();
acked_ticks.register_tick(*replicon_tick, change_tick.this_run());
acked_ticks.register_tick(**server_tick, change_tick.this_run());

let buffers = prepare_buffers(&mut buffers, &acked_ticks, *replicon_tick)?;
let buffers = prepare_buffers(&mut buffers, &acked_ticks, **server_tick)?;
collect_changes(
buffers,
set.p0(),
Expand Down Expand Up @@ -402,6 +402,13 @@ pub enum TickPolicy {
Manual,
}

/// A tick that increments each time we need the server to compute and send an update.
///
/// Mapped to the Bevy's `Tick` in [`AckedTicks`].
/// See also [`TickPolicy`].
#[derive(Default, Deref, DerefMut, Resource)]
pub struct ServerTick(RepliconTick);

/// Stores information about ticks.
///
/// Used only on server.
Expand Down Expand Up @@ -680,46 +687,6 @@ impl ReplicationBuffer {
}
}

/// A tick that increments each time we need the server to compute and send an update.
///
/// Mapped to the Bevy's `Tick` in [`AckedTicks`].
/// See also [`TickPolicy`].
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Resource, Serialize)]
pub struct RepliconTick(u32);

impl RepliconTick {
/// Gets the value of this network tick.
#[inline]
pub fn get(self) -> u32 {
self.0
}

/// Increments current tick by the specified `value` and takes wrapping into account.
#[inline]
pub fn increment_by(&mut self, value: u32) {
self.0 = self.0.wrapping_add(value);
}

/// Same as [`Self::increment_by`], but increments only by 1.
#[inline]
pub fn increment(&mut self) {
self.increment_by(1)
}
}

impl PartialOrd for RepliconTick {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let difference = self.0.wrapping_sub(other.0);
if difference == 0 {
Some(Ordering::Equal)
} else if difference > u32::MAX / 2 {
Some(Ordering::Less)
} else {
Some(Ordering::Greater)
}
}
}

/// Fills scene with all replicated entities and their components.
///
/// # Panics
Expand Down Expand Up @@ -779,15 +746,3 @@ pub fn replicate_into_scene(scene: &mut DynamicScene, world: &World) {
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn tick_comparsion() {
assert_eq!(RepliconTick(0), RepliconTick(0));
assert!(RepliconTick(0) < RepliconTick(1));
assert!(RepliconTick(0) > RepliconTick(u32::MAX));
}
}

0 comments on commit f89c79f

Please sign in to comment.