Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to Bevy 0.13 #106

Merged
merged 2 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ categories = ["network-programming", "game-development"]
wasm-bindgen = ["instant/wasm-bindgen", "ggrs/wasm-bindgen"]

[dependencies]
bevy = { version = "0.12", default-features = false }
bevy = { version = "0.13", default-features = false }
bytemuck = { version = "1.7", features = ["derive"] }
instant = { version = "0.1", optional = true }
log = "0.4"
Expand All @@ -25,11 +25,11 @@ ggrs = { git = "https://github.com/gschup/ggrs", features = ["sync-send"] }
seahash = "4.1"

[dev-dependencies]
bevy = { version = "0.12", default-features = true }
bevy = { version = "0.13", default-features = true }
clap = { version = "4.4", features = ["derive"] }
rand = "0.8.4"
rand_xoshiro = "0.6"
serde = "1.0.130"
serde = "1.0.196"
serde_json = "1.0"
serial_test = "2.0"

Expand Down
24 changes: 12 additions & 12 deletions examples/box_game/box_game.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bevy::{prelude::*, utils::HashMap};
use bevy::{prelude::*, render::mesh::PlaneMeshBuilder, utils::HashMap};
use bevy_ggrs::{
AddRollbackCommandExtension, GgrsConfig, LocalInputs, LocalPlayers, PlayerInputs, Rollback,
Session,
Expand Down Expand Up @@ -54,24 +54,24 @@ pub struct FrameCount {
/// Collects player inputs during [`ReadInputs`](`bevy_ggrs::ReadInputs`) and creates a [`LocalInputs`] resource.
pub fn read_local_inputs(
mut commands: Commands,
keyboard_input: Res<Input<KeyCode>>,
keyboard_input: Res<ButtonInput<KeyCode>>,
local_players: Res<LocalPlayers>,
) {
let mut local_inputs = HashMap::new();

for handle in &local_players.0 {
let mut input: u8 = 0;

if keyboard_input.pressed(KeyCode::W) {
if keyboard_input.pressed(KeyCode::KeyW) {
input |= INPUT_UP;
}
if keyboard_input.pressed(KeyCode::A) {
if keyboard_input.pressed(KeyCode::KeyA) {
input |= INPUT_LEFT;
}
if keyboard_input.pressed(KeyCode::S) {
if keyboard_input.pressed(KeyCode::KeyS) {
input |= INPUT_DOWN;
}
if keyboard_input.pressed(KeyCode::D) {
if keyboard_input.pressed(KeyCode::KeyD) {
input |= INPUT_RIGHT;
}

Expand All @@ -95,16 +95,16 @@ pub fn setup_system(

// A ground plane
commands.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane {
size: PLANE_SIZE,
..default()
mesh: meshes.add(Mesh::from(PlaneMeshBuilder {
plane: Plane3d::new(Vec3::Y),
half_size: Vec2::splat(PLANE_SIZE / 2.0),
})),
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
material: materials.add(StandardMaterial::from(Color::rgb(0.3, 0.5, 0.3))),
..default()
});

let r = PLANE_SIZE / 4.;
let mesh = meshes.add(Mesh::from(shape::Cube { size: CUBE_SIZE }));
let mesh = meshes.add(Mesh::from(Cuboid::from_size(Vec3::splat(CUBE_SIZE))));

for handle in 0..num_players {
let rot = handle as f32 / num_players as f32 * 2. * std::f32::consts::PI;
Expand All @@ -123,7 +123,7 @@ pub fn setup_system(
// ...add visual information...
PbrBundle {
mesh: mesh.clone(),
material: materials.add(color.into()),
material: materials.add(StandardMaterial::from(color)),
transform,
johanhelsing marked this conversation as resolved.
Show resolved Hide resolved
..default()
},
Expand Down
4 changes: 2 additions & 2 deletions examples/stress_tests/particles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const INPUT_NOOP: u8 = 1 << 5;

fn read_local_inputs(
mut commands: Commands,
keyboard_input: Res<Input<KeyCode>>,
keyboard_input: Res<ButtonInput<KeyCode>>,
local_players: Res<LocalPlayers>,
) {
let mut local_inputs = HashMap::new();
Expand All @@ -88,7 +88,7 @@ fn read_local_inputs(
}

// n is a no-op key, press to simply trigger a rollback
if keyboard_input.pressed(KeyCode::N) {
if keyboard_input.pressed(KeyCode::KeyN) {
input |= INPUT_NOOP;
}

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//!
//! See [`GgrsPlugin`] for getting started.
#![forbid(unsafe_code)] // let us try
#![allow(clippy::type_complexity)] // Suppress warnings around Query

use bevy::{
ecs::{
Expand Down
4 changes: 2 additions & 2 deletions src/rollback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ pub trait AddRollbackCommandExtension: private::AddRollbackCommandExtensionSeal
fn add_rollback(&mut self) -> &mut Self;
}

impl<'w, 's, 'a> private::AddRollbackCommandExtensionSeal for EntityCommands<'w, 's, 'a> {}
impl<'a> private::AddRollbackCommandExtensionSeal for EntityCommands<'a> {}

impl<'w, 's, 'a> AddRollbackCommandExtension for EntityCommands<'w, 's, 'a> {
impl<'a> AddRollbackCommandExtension for EntityCommands<'a> {
fn add_rollback(&mut self) -> &mut Self {
self.add(AddRollbackCommand);
self
Expand Down
58 changes: 8 additions & 50 deletions src/snapshot/component_map.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use std::marker::PhantomData;

use bevy::{
ecs::entity::{EntityMapper, MapEntities},
prelude::*,
};
use bevy::{ecs::entity::MapEntities, prelude::*};

use crate::{LoadWorld, LoadWorldSet, RollbackEntityMap};

Expand All @@ -26,8 +23,8 @@ use crate::{LoadWorld, LoadWorldSet, RollbackEntityMap};
/// struct BestFriend(Entity);
///
/// impl MapEntities for BestFriend {
/// fn map_entities(&mut self, entity_mapper: &mut EntityMapper) {
/// self.0 = entity_mapper.get_or_reserve(self.0);
/// fn map_entities<M: EntityMapper>(&mut self, entity_mapper: &mut M) {
/// self.0 = entity_mapper.map_entity(self.0);
/// }
/// }
///
Expand Down Expand Up @@ -72,55 +69,16 @@ fn apply_rollback_map_to_component_inner<C>(world: &mut World, map: Mut<Rollback
where
C: Component + MapEntities,
{
let mut applied_entity_map = map.generate_map();

EntityMapper::world_scope(&mut applied_entity_map, world, apply_map::<C>);
for (original, _new) in map.iter() {
if let Some(mut component) = world.get_mut::<C>(original) {
component.map_entities(&mut map.as_ref());
}
}

trace!(
"Mapped {}",
bevy::utils::get_short_name(std::any::type_name::<C>())
);

// If the entity map is now larger than the set of rollback entities, then dead entities were created.
// TODO: This workaround is required because the current behavior of `map_all_entities` is to change all entities,
// creating dead entities instead of leaving them with their original value. If `EntityMapper` behavior changes,
// then this workaround may no longer be required.
johanhelsing marked this conversation as resolved.
Show resolved Hide resolved
if applied_entity_map.len() > map.len() {
// Reverse dead-mappings, no-op correct mappings
for original in applied_entity_map.keys().copied().collect::<Vec<_>>() {
let mapped = applied_entity_map.remove(&original).unwrap();

if map.get(original).is_some() {
// Rollback entity was correctly mapped; no-op
applied_entity_map.insert(mapped, mapped);
} else {
// An untracked bystander was mapped to a dead end; reverse
applied_entity_map.insert(mapped, original);
}
}

// Map entities a second time, fixing dead entities
EntityMapper::world_scope(&mut applied_entity_map, world, apply_map::<C>);

trace!(
"Re-Mapped {}",
bevy::utils::get_short_name(std::any::type_name::<C>())
);
}
}

fn apply_map<C: Component + MapEntities>(world: &mut World, entity_mapper: &mut EntityMapper) {
let entities = entity_mapper
.get_map()
.values()
.copied()
.collect::<Vec<Entity>>();

for entity in &entities {
if let Some(mut component) = world.get_mut::<C>(*entity) {
component.map_entities(entity_mapper);
}
}
}

impl<C> Plugin for ComponentMapEntitiesPlugin<C>
Expand Down
48 changes: 6 additions & 42 deletions src/snapshot/resource_map.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use std::marker::PhantomData;

use bevy::{
ecs::entity::{EntityMapper, MapEntities},
prelude::*,
};
use bevy::{ecs::entity::MapEntities, prelude::*};

use crate::{LoadWorld, LoadWorldSet, RollbackEntityMap};

Expand All @@ -26,8 +23,8 @@ use crate::{LoadWorld, LoadWorldSet, RollbackEntityMap};
/// struct Player(Entity);
///
/// impl MapEntities for Player {
/// fn map_entities(&mut self, entity_mapper: &mut EntityMapper) {
/// self.0 = entity_mapper.get_or_reserve(self.0);
/// fn map_entities<M: EntityMapper>(&mut self, entity_mapper: &mut M) {
/// self.0 = entity_mapper.map_entity(self.0);
/// }
/// }
///
Expand Down Expand Up @@ -72,47 +69,14 @@ fn apply_rollback_map_to_resource_inner<R>(world: &mut World, map: Mut<RollbackE
where
R: Resource + MapEntities,
{
let mut applied_entity_map = map.generate_map();

EntityMapper::world_scope(&mut applied_entity_map, world, apply_map::<R>);
if let Some(mut resource) = world.get_resource_mut::<R>() {
resource.map_entities(&mut map.as_ref());
}

trace!(
"Mapped {}",
bevy::utils::get_short_name(std::any::type_name::<R>())
);

// If the entity map is now larger than the set of rollback entities, then dead entities were created.
// TODO: This workaround is required because the current behavior of `map_all_entities` is to change all entities,
// creating dead entities instead of leaving them with their original value. If `EntityMapper` behavior changes,
// then this workaround may no longer be required.
if applied_entity_map.len() > map.len() {
// Reverse dead-mappings, no-op correct mappings
for original in applied_entity_map.keys().copied().collect::<Vec<_>>() {
let mapped = applied_entity_map.remove(&original).unwrap();

if map.get(original).is_some() {
// Rollback entity was correctly mapped; no-op
applied_entity_map.insert(mapped, mapped);
} else {
// An untracked bystander was mapped to a dead end; reverse
applied_entity_map.insert(mapped, original);
}
}

// Map entities a second time, fixing dead entities
EntityMapper::world_scope(&mut applied_entity_map, world, apply_map::<R>);

trace!(
"Re-Mapped {}",
bevy::utils::get_short_name(std::any::type_name::<R>())
);
}
}

fn apply_map<R: Resource + MapEntities>(world: &mut World, entity_mapper: &mut EntityMapper) {
if let Some(mut resource) = world.get_resource_mut::<R>() {
resource.map_entities(entity_mapper);
}
}

impl<R> Plugin for ResourceMapEntitiesPlugin<R>
Expand Down
25 changes: 22 additions & 3 deletions src/snapshot/rollback_entity_map.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
use bevy::{prelude::*, utils::HashMap};
use bevy::{ecs::entity::EntityHashMap, prelude::*, utils::HashMap};

/// A [`Resource`] which provides an [`EntityMap`], describing how [`Entities`](`Entity`)
/// changed during a rollback.
#[derive(Resource, Default)]
pub struct RollbackEntityMap(HashMap<Entity, Entity>);
pub struct RollbackEntityMap(EntityHashMap<Entity>);

impl From<EntityHashMap<Entity>> for RollbackEntityMap {
fn from(value: EntityHashMap<Entity>) -> Self {
Self(value)
}
}

impl From<HashMap<Entity, Entity>> for RollbackEntityMap {
fn from(value: HashMap<Entity, Entity>) -> Self {
Self(value.into_iter().collect())
}
}

impl RollbackEntityMap {
/// Create a new [`RollbackEntityMap`], which can generate [`EntityMaps`](`EntityMap`) as required.
pub fn new(map: HashMap<Entity, Entity>) -> Self {
Self(map)
map.into()
}

/// Generate an owned [`EntityMap`], which can be used concurrently with other systems.
Expand Down Expand Up @@ -46,3 +58,10 @@ impl RollbackEntityMap {
map.is_empty()
}
}

impl<'a> EntityMapper for &'a RollbackEntityMap {
/// Map the provided [`Entity`], or return it unmodified if it does not need to be mapped.
fn map_entity(&mut self, entity: Entity) -> Entity {
self.get(entity).unwrap_or(entity)
}
}
2 changes: 1 addition & 1 deletion src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl GgrsTimePlugin {

impl Plugin for GgrsTimePlugin {
fn build(&self, app: &mut App) {
app.insert_resource(Time::new_with(GgrsTime::default()))
app.insert_resource(Time::new_with(GgrsTime))
.add_plugins(ResourceSnapshotPlugin::<CloneStrategy<Time<GgrsTime>>>::default())
.add_systems(
AdvanceWorld,
Expand Down
Loading
Loading