aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/src
diff options
context:
space:
mode:
Diffstat (limited to 'azalea-client/src')
-rw-r--r--azalea-client/src/attack.rs6
-rw-r--r--azalea-client/src/interact.rs3
-rw-r--r--azalea-client/src/mining.rs2
-rw-r--r--azalea-client/src/movement.rs55
-rw-r--r--azalea-client/src/packet_handling/game.rs44
5 files changed, 82 insertions, 28 deletions
diff --git a/azalea-client/src/attack.rs b/azalea-client/src/attack.rs
index 644af5de..56f3b1d0 100644
--- a/azalea-client/src/attack.rs
+++ b/azalea-client/src/attack.rs
@@ -15,7 +15,7 @@ use derive_more::{Deref, DerefMut};
use crate::{
interact::SwingArmEvent,
local_player::{LocalGameMode, SendPacketEvent},
- movement::walk_listener,
+ movement::MoveEventsSet,
respawn::perform_respawn,
Client,
};
@@ -28,7 +28,7 @@ impl Plugin for AttackPlugin {
Update,
handle_attack_event
.before(update_bounding_box)
- .before(walk_listener)
+ .before(MoveEventsSet)
.after(perform_respawn),
)
.add_systems(
@@ -106,7 +106,7 @@ pub fn handle_attack_event(
ticks_since_last_attack.0 = 0;
- physics.delta = physics.delta.multiply(0.6, 1.0, 0.6);
+ physics.velocity = physics.velocity.multiply(0.6, 1.0, 0.6);
**sprinting = false;
}
}
diff --git a/azalea-client/src/interact.rs b/azalea-client/src/interact.rs
index b7b47ec6..32b68925 100644
--- a/azalea-client/src/interact.rs
+++ b/azalea-client/src/interact.rs
@@ -37,6 +37,7 @@ use crate::{
local_player::{
handle_send_packet_event, LocalGameMode, PermissionLevel, PlayerAbilities, SendPacketEvent,
},
+ movement::MoveEventsSet,
respawn::perform_respawn,
Client,
};
@@ -62,7 +63,7 @@ impl Plugin for InteractPlugin {
.chain(),
update_modifiers_for_held_item
.after(InventorySet)
- .after(crate::movement::walk_listener),
+ .after(MoveEventsSet),
),
);
}
diff --git a/azalea-client/src/mining.rs b/azalea-client/src/mining.rs
index 806a7b91..e1193f73 100644
--- a/azalea-client/src/mining.rs
+++ b/azalea-client/src/mining.rs
@@ -18,6 +18,7 @@ use crate::{
},
inventory::{InventoryComponent, InventorySet},
local_player::{LocalGameMode, PermissionLevel, PlayerAbilities, SendPacketEvent},
+ movement::MoveEventsSet,
Client,
};
@@ -43,6 +44,7 @@ impl Plugin for MinePlugin {
.chain()
.in_set(MiningSet)
.after(InventorySet)
+ .after(MoveEventsSet)
.before(azalea_entity::update_bounding_box)
.after(azalea_entity::update_fluid_on_eyes)
.after(crate::interact::update_hit_result_component)
diff --git a/azalea-client/src/movement.rs b/azalea-client/src/movement.rs
index 28628115..f4bb8836 100644
--- a/azalea-client/src/movement.rs
+++ b/azalea-client/src/movement.rs
@@ -1,5 +1,6 @@
use crate::client::Client;
use crate::local_player::SendPacketEvent;
+use azalea_core::position::Vec3;
use azalea_entity::{metadata::Sprinting, Attributes, Jumping};
use azalea_entity::{InLoadedChunk, LastSentPosition, LookDirection, Physics, Position};
use azalea_physics::{ai_step, PhysicsSet};
@@ -13,6 +14,7 @@ use azalea_protocol::packets::game::{
use azalea_world::{MinecraftEntityId, MoveEntityError};
use bevy_app::{App, FixedUpdate, Plugin, Update};
use bevy_ecs::prelude::{Event, EventWriter};
+use bevy_ecs::schedule::SystemSet;
use bevy_ecs::{
component::Component, entity::Entity, event::EventReader, query::With,
schedule::IntoSystemConfigs, system::Query,
@@ -44,7 +46,13 @@ impl Plugin for PlayerMovePlugin {
fn build(&self, app: &mut App) {
app.add_event::<StartWalkEvent>()
.add_event::<StartSprintEvent>()
- .add_systems(Update, (sprint_listener, walk_listener).chain())
+ .add_event::<KnockbackEvent>()
+ .add_systems(
+ Update,
+ (handle_sprint, handle_walk, handle_knockback)
+ .chain()
+ .in_set(MoveEventsSet),
+ )
.add_systems(
FixedUpdate,
(
@@ -60,6 +68,9 @@ impl Plugin for PlayerMovePlugin {
}
}
+#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
+pub struct MoveEventsSet;
+
impl Client {
/// Set whether we're jumping. This acts as if you held space in
/// vanilla. If you want to jump once, use the `jump` function.
@@ -391,10 +402,9 @@ pub struct StartWalkEvent {
pub direction: WalkDirection,
}
-/// Start walking in the given direction. To sprint, use
-/// [`Client::sprint`]. To stop walking, call walk with
-/// `WalkDirection::None`.
-pub fn walk_listener(
+/// The system that makes the player start walking when they receive a
+/// [`StartWalkEvent`].
+pub fn handle_walk(
mut events: EventReader<StartWalkEvent>,
mut query: Query<(&mut PhysicsState, &mut Sprinting, &mut Attributes)>,
) {
@@ -415,8 +425,9 @@ pub struct StartSprintEvent {
pub entity: Entity,
pub direction: SprintDirection,
}
-/// Start sprinting in the given direction.
-pub fn sprint_listener(
+/// The system that makes the player start sprinting when they receive a
+/// [`StartSprintEvent`].
+pub fn handle_sprint(
mut query: Query<&mut PhysicsState>,
mut events: EventReader<StartSprintEvent>,
) {
@@ -459,6 +470,36 @@ fn has_enough_impulse_to_start_sprinting(physics_state: &PhysicsState) -> bool {
// }
}
+/// An event sent by the server that sets or adds to our velocity. Usually
+/// `KnockbackKind::Set` is used for normal knockback and `KnockbackKind::Add`
+/// is used for explosions, but some servers (notably Hypixel) use explosions
+/// for knockback.
+#[derive(Event)]
+pub struct KnockbackEvent {
+ pub entity: Entity,
+ pub kind: KnockbackType,
+}
+
+pub enum KnockbackType {
+ Set(Vec3),
+ Add(Vec3),
+}
+
+pub fn handle_knockback(mut query: Query<&mut Physics>, mut events: EventReader<KnockbackEvent>) {
+ for event in events.iter() {
+ if let Ok(mut physics) = query.get_mut(event.entity) {
+ match event.kind {
+ KnockbackType::Set(velocity) => {
+ physics.velocity = velocity;
+ }
+ KnockbackType::Add(velocity) => {
+ physics.velocity += velocity;
+ }
+ }
+ }
+ }
+}
+
#[derive(Clone, Copy, Debug, Default)]
pub enum WalkDirection {
#[default]
diff --git a/azalea-client/src/packet_handling/game.rs b/azalea-client/src/packet_handling/game.rs
index 6e138565..1d8c6cc9 100644
--- a/azalea-client/src/packet_handling/game.rs
+++ b/azalea-client/src/packet_handling/game.rs
@@ -44,6 +44,7 @@ use crate::{
GameProfileComponent, Hunger, InstanceHolder, LocalGameMode, PlayerAbilities,
SendPacketEvent, TabList,
},
+ movement::{KnockbackEvent, KnockbackType},
raw_connection::RawConnection,
ClientInformation, PlayerInfo, ReceivedRegistries,
};
@@ -422,7 +423,7 @@ pub fn process_packet_events(ecs: &mut World) {
continue;
};
- let delta_movement = physics.delta;
+ let delta_movement = physics.velocity;
let is_x_relative = p.relative_arguments.x;
let is_y_relative = p.relative_arguments.y;
@@ -459,7 +460,7 @@ pub fn process_packet_events(ecs: &mut World) {
y_rot += direction.y_rot;
}
- physics.delta = Vec3 {
+ physics.velocity = Vec3 {
x: delta_x,
y: delta_y,
z: delta_z,
@@ -797,15 +798,21 @@ pub fn process_packet_events(ecs: &mut World) {
continue;
};
+ // this is to make sure the same entity velocity update doesn't get sent
+ // multiple times when in swarms
commands.entity(entity).add(RelativeEntityUpdate {
partial_world: instance_holder.partial_instance.clone(),
- update: Box::new(move |entity| {
- let mut physics = entity.get_mut::<Physics>().unwrap();
- physics.delta = Vec3 {
- x: p.xa as f64 / 8000.,
- y: p.ya as f64 / 8000.,
- z: p.za as f64 / 8000.,
- };
+ update: Box::new(move |entity_mut| {
+ entity_mut.world_scope(|world| {
+ world.send_event(KnockbackEvent {
+ entity,
+ kind: KnockbackType::Set(Vec3 {
+ x: p.xa as f64 / 8000.,
+ y: p.ya as f64 / 8000.,
+ z: p.za as f64 / 8000.,
+ }),
+ })
+ });
}),
});
@@ -1186,15 +1193,18 @@ pub fn process_packet_events(ecs: &mut World) {
ClientboundGamePacket::DeleteChat(_) => {}
ClientboundGamePacket::Explode(p) => {
trace!("Got explode packet {p:?}");
- let mut system_state: SystemState<Query<&mut Physics>> = SystemState::new(ecs);
- let mut query = system_state.get_mut(ecs);
- let mut physics = query.get_mut(player_entity).unwrap();
+ let mut system_state: SystemState<EventWriter<KnockbackEvent>> =
+ SystemState::new(ecs);
+ let mut knockback_events = system_state.get_mut(ecs);
- physics.delta += Vec3 {
- x: p.knockback_x as f64,
- y: p.knockback_y as f64,
- z: p.knockback_z as f64,
- };
+ knockback_events.send(KnockbackEvent {
+ entity: player_entity,
+ kind: KnockbackType::Set(Vec3 {
+ x: p.knockback_x as f64,
+ y: p.knockback_y as f64,
+ z: p.knockback_z as f64,
+ }),
+ });
system_state.apply(ecs);
}