Bevy 0.17 Migration Final PR (#76)
* Get bevy 0.17 compiling and running (#72) * get bevy 0.17 compiling and running * try to fix CI breaking from const assertion for client/server features * fix `bin` -> `lib` for `shared` in CI * typo * fix some collider issues (#73) * Physics/controller improvements (#74) * trying to fix physics prediction * fixed prediction desync * substantial controller improvements * Finish off main bevy 0.17 migration (#75) * fix lookdir issues - airplane moving backwards - player model facing backwards - camera was technically backwards the whole time, and player models were facing the right way; camera is now facing forwards - firing without a target now respects lookdir * fix aim targeting * migrate to bevy_trenchbroom 0.10 crates release * fixed colliders not being adjusted out of worldspace * predict platforms to stop constant rollbacks while riding them * fix key/head drop visuals not working * Fix key/head drop random initial force * fixed static head drops duplicating * fix platform velocity inheritance * fix thrown projectiles not autorotating * fix inconsistent explosion animations * update avian3d to 0.4.1 * fix controller snapping to fixed angle upon switching heads * clean up commented code * fix broken physics positions * Clean comments, fix warnings (#77) * clean comments, fix warnings * fix missing import * steamworks 162 libs * fix mouselook --------- Co-authored-by: extrawurst <mail@rusticorn.com>
This commit is contained in:
@@ -1,17 +1,29 @@
|
||||
use bevy::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Component, Reflect)]
|
||||
#[derive(Component, Reflect, PartialEq, Serialize, Deserialize)]
|
||||
#[reflect(Component)]
|
||||
pub struct AutoRotation(pub Quat);
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.register_type::<AutoRotation>();
|
||||
|
||||
app.add_systems(FixedUpdate, update_auto_rotation);
|
||||
#[cfg(feature = "client")]
|
||||
app.add_systems(Update, update_auto_rotation);
|
||||
}
|
||||
|
||||
fn update_auto_rotation(mut query: Query<(&AutoRotation, &mut Transform)>) {
|
||||
for (auto_rotation, mut transform) in query.iter_mut() {
|
||||
transform.rotate_local(auto_rotation.0);
|
||||
#[cfg(feature = "client")]
|
||||
fn update_auto_rotation(
|
||||
query: Query<(&AutoRotation, &Children)>,
|
||||
mut meshes: Query<&mut Transform>,
|
||||
) {
|
||||
for (auto_rotation, children) in query.iter() {
|
||||
for &child in children {
|
||||
let Ok(mut transform) = meshes.get_mut(child) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
transform.rotate_local(auto_rotation.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::camera::MainCamera;
|
||||
use bevy::prelude::*;
|
||||
use bevy_sprite3d::Sprite3dPlugin;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Component, Reflect, Default, PartialEq, Eq)]
|
||||
#[derive(Component, Reflect, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[reflect(Component)]
|
||||
pub enum Billboard {
|
||||
#[default]
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
use bevy::ecs::{
|
||||
event::Event,
|
||||
entity::Entity,
|
||||
event::{EntityEvent, Event},
|
||||
system::{Commands, EntityCommands},
|
||||
world::{EntityWorldMut, World},
|
||||
};
|
||||
use lightyear::prelude::Disconnected;
|
||||
|
||||
pub trait CommandExt {
|
||||
fn trigger_server(&mut self, event: impl Event) -> &mut Self;
|
||||
fn trigger_server<'a, E: Event<Trigger<'a>: Default>>(&mut self, event: E) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'w, 's> CommandExt for Commands<'w, 's> {
|
||||
fn trigger_server(&mut self, event: impl Event) -> &mut Self {
|
||||
fn trigger_server<'a, E: Event<Trigger<'a>: Default>>(&mut self, event: E) -> &mut Self {
|
||||
self.queue(|world: &mut World| {
|
||||
let mut query_state = world.query::<&Disconnected>();
|
||||
if cfg!(feature = "server") || !query_state.query(world).is_empty() {
|
||||
@@ -22,11 +23,17 @@ impl<'w, 's> CommandExt for Commands<'w, 's> {
|
||||
}
|
||||
|
||||
pub trait EntityCommandExt {
|
||||
fn trigger_server(&mut self, event: impl Event) -> &mut Self;
|
||||
fn trigger_server<'a, E: EntityEvent<Trigger<'a>: Default>>(
|
||||
&mut self,
|
||||
event: impl FnOnce(Entity) -> E + Send + Sync + 'static,
|
||||
) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'w> EntityCommandExt for EntityCommands<'w> {
|
||||
fn trigger_server(&mut self, event: impl Event) -> &mut Self {
|
||||
fn trigger_server<'a, E: EntityEvent<Trigger<'a>: Default>>(
|
||||
&mut self,
|
||||
event: impl FnOnce(Entity) -> E + Send + Sync + 'static,
|
||||
) -> &mut Self {
|
||||
self.queue(|mut entity: EntityWorldMut| {
|
||||
let mut query_state = entity.world_scope(|world| world.query::<&Disconnected>());
|
||||
if cfg!(feature = "server") || !query_state.query(entity.world()).is_empty() {
|
||||
|
||||
@@ -13,11 +13,7 @@ pub fn plugin(app: &mut App) {
|
||||
global_observer!(app, on_explosion);
|
||||
}
|
||||
|
||||
fn on_explosion(
|
||||
explosion: Trigger<Explosion>,
|
||||
mut commands: Commands,
|
||||
spatial_query: SpatialQuery,
|
||||
) {
|
||||
fn on_explosion(explosion: On<Explosion>, mut commands: Commands, spatial_query: SpatialQuery) {
|
||||
let explosion = explosion.event();
|
||||
let intersections = {
|
||||
spatial_query.shape_intersections(
|
||||
@@ -32,7 +28,8 @@ fn on_explosion(
|
||||
|
||||
for entity in intersections.iter() {
|
||||
if let Ok(mut e) = commands.get_entity(*entity) {
|
||||
e.trigger(Hit {
|
||||
e.trigger(|entity| Hit {
|
||||
entity,
|
||||
damage: explosion.damage,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ pub mod billboards;
|
||||
pub mod commands;
|
||||
pub mod explosions;
|
||||
pub mod observers;
|
||||
pub mod one_shot_force;
|
||||
pub mod run_conditions;
|
||||
pub mod sprite_3d_animation;
|
||||
pub mod squish_animation;
|
||||
@@ -14,4 +15,5 @@ pub(crate) use observers::global_observer;
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.add_plugins(observers::plugin);
|
||||
app.add_plugins(one_shot_force::plugin);
|
||||
}
|
||||
|
||||
19
crates/shared/src/utils/one_shot_force.rs
Normal file
19
crates/shared/src/utils/one_shot_force.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use avian3d::prelude::{Forces, RigidBodyForces};
|
||||
use bevy::prelude::*;
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.add_systems(FixedUpdate, apply_one_shot_forces);
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct OneShotForce(pub Vec3);
|
||||
|
||||
pub fn apply_one_shot_forces(
|
||||
mut commands: Commands,
|
||||
mut query: Query<(Entity, &OneShotForce, Forces)>,
|
||||
) {
|
||||
for (entity, force, mut forces) in query.iter_mut() {
|
||||
forces.apply_force(force.0);
|
||||
commands.entity(entity).remove::<OneShotForce>();
|
||||
}
|
||||
}
|
||||
@@ -18,16 +18,19 @@ pub fn plugin(app: &mut App) {
|
||||
fn animate_sprite(
|
||||
mut commands: Commands,
|
||||
time: Res<Time>,
|
||||
mut query: Query<(Entity, &mut AnimationTimer, &mut Sprite3d)>,
|
||||
mut query: Query<(Entity, &mut AnimationTimer, &Sprite3d, &mut Sprite)>,
|
||||
) {
|
||||
for (e, mut timer, mut sprite_3d) in query.iter_mut() {
|
||||
timer.tick(time.delta());
|
||||
if timer.just_finished() {
|
||||
let length = sprite_3d.texture_atlas_keys.as_ref().unwrap().len();
|
||||
let atlas = sprite_3d.texture_atlas.as_mut().unwrap();
|
||||
for (e, mut timer, sprite_3d, mut sprite) in query.iter_mut() {
|
||||
let length = sprite_3d.texture_atlas_keys.len();
|
||||
let atlas = sprite.texture_atlas.as_mut().unwrap();
|
||||
|
||||
if atlas.index < length - 1 {
|
||||
atlas.index = atlas.index.saturating_add(1) % length;
|
||||
if length > 0 {
|
||||
timer.tick(time.delta());
|
||||
}
|
||||
|
||||
if timer.just_finished() {
|
||||
if atlas.index + 1 < length {
|
||||
atlas.index = (atlas.index + 1) % length;
|
||||
} else {
|
||||
commands.entity(e).despawn();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use bevy::prelude::*;
|
||||
use ops::sin;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Component, Reflect)]
|
||||
#[derive(Component, Reflect, PartialEq, Serialize, Deserialize)]
|
||||
#[reflect(Component)]
|
||||
pub struct SquishAnimation(pub f32);
|
||||
|
||||
|
||||
@@ -1,54 +1,60 @@
|
||||
use crate::utils::global_observer;
|
||||
use bevy::{ecs::system::SystemParam, prelude::*};
|
||||
use lightyear::prelude::{AppTriggerExt, Channel, NetworkDirection, RemoteTrigger, TriggerSender};
|
||||
use lightyear::prelude::{AppTriggerExt, Channel, EventSender, NetworkDirection, RemoteEvent};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(SystemParam)]
|
||||
pub struct ServerMultiTriggerSender<'w, 's, M: Event + Clone> {
|
||||
senders: Query<'w, 's, &'static mut TriggerSender<M>>,
|
||||
senders: Query<'w, 's, &'static mut EventSender<M>>,
|
||||
}
|
||||
|
||||
impl<'w, 's, M: Event + Clone> ServerMultiTriggerSender<'w, 's, M> {
|
||||
pub fn server_trigger_targets<C: Channel>(&mut self, trigger: M, target: &[Entity]) {
|
||||
pub fn server_trigger_targets<C: Channel>(&mut self, event: M) {
|
||||
if cfg!(not(feature = "server")) {
|
||||
return;
|
||||
}
|
||||
|
||||
for mut sender in self.senders.iter_mut() {
|
||||
sender.trigger_targets::<C>(trigger.clone(), target.iter().copied());
|
||||
sender.trigger::<C>(event.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TriggerAppExt {
|
||||
fn replicate_trigger<M: Event + Clone + Serialize + for<'de> Deserialize<'de>, C: Channel>(
|
||||
fn replicate_event<
|
||||
'a,
|
||||
M: Event<Trigger<'a>: Default> + Clone + Serialize + for<'de> Deserialize<'de>,
|
||||
C: Channel,
|
||||
>(
|
||||
&mut self,
|
||||
);
|
||||
}
|
||||
|
||||
impl TriggerAppExt for App {
|
||||
fn replicate_trigger<M: Event + Clone + Serialize + for<'de> Deserialize<'de>, C: Channel>(
|
||||
fn replicate_event<
|
||||
'a,
|
||||
M: Event<Trigger<'a>: Default> + Clone + Serialize + for<'de> Deserialize<'de>,
|
||||
C: Channel,
|
||||
>(
|
||||
&mut self,
|
||||
) {
|
||||
self.add_trigger::<M>()
|
||||
self.register_event::<M>()
|
||||
.add_direction(NetworkDirection::ServerToClient);
|
||||
global_observer!(self, replicate_trigger_to_clients::<M, C>);
|
||||
global_observer!(self, remote_to_local_trigger::<M>);
|
||||
global_observer!(self, remote_to_local_event::<M>);
|
||||
}
|
||||
}
|
||||
|
||||
fn replicate_trigger_to_clients<M: Event + Clone, C: Channel>(
|
||||
trigger: Trigger<M>,
|
||||
on: On<M>,
|
||||
mut sender: ServerMultiTriggerSender<M>,
|
||||
) {
|
||||
let targets: &[Entity] = if trigger.target() == Entity::PLACEHOLDER {
|
||||
&[]
|
||||
} else {
|
||||
&[trigger.target()]
|
||||
};
|
||||
sender.server_trigger_targets::<C>(trigger.event().clone(), targets);
|
||||
sender.server_trigger_targets::<C>(on.event().clone());
|
||||
}
|
||||
|
||||
fn remote_to_local_trigger<M: Event + Clone>(trigger: Trigger<RemoteTrigger<M>>, mut c: Commands) {
|
||||
c.trigger_targets(trigger.event().trigger.clone(), trigger.target());
|
||||
fn remote_to_local_event<'a, M: Event<Trigger<'a>: Default> + Clone>(
|
||||
trigger: On<RemoteEvent<M>>,
|
||||
mut c: Commands,
|
||||
) {
|
||||
c.trigger(trigger.event().trigger.clone());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user