1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

KnockbackEvent and rename Physics::delta to velocity

This commit is contained in:
mat 2023-10-12 22:39:29 -05:00
parent 79ad1e93bf
commit eeec59adab
12 changed files with 112 additions and 58 deletions

View file

@ -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;
}
}

View file

@ -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),
),
);
}

View file

@ -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)

View file

@ -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]

View file

@ -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 {
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 {
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);
}

View file

@ -35,7 +35,7 @@ pub fn move_relative(
acceleration: &Vec3,
) {
let input_vector = input_vector(direction, speed, acceleration);
physics.delta += input_vector;
physics.velocity += input_vector;
}
pub fn input_vector(direction: &LookDirection, speed: f32, acceleration: &Vec3) -> Vec3 {
@ -208,7 +208,8 @@ pub struct LookDirection {
/// bounding box.
#[derive(Debug, Component, Clone)]
pub struct Physics {
pub delta: Vec3,
/// How fast the entity is moving.
pub velocity: Vec3,
/// X acceleration.
pub xxa: f32,
@ -232,7 +233,7 @@ pub struct Physics {
impl Physics {
pub fn new(dimensions: EntityDimensions, pos: &Vec3) -> Self {
Self {
delta: Vec3::default(),
velocity: Vec3::default(),
xxa: 0.,
yya: 0.,

View file

@ -201,8 +201,8 @@ pub fn move_colliding(
// if self.isRemoved() { return; }
if horizontal_collision {
let delta_movement = &physics.delta;
physics.delta = Vec3 {
let delta_movement = &physics.velocity;
physics.velocity = Vec3 {
x: if x_collision { 0. } else { delta_movement.x },
y: delta_movement.y,
z: if z_collision { 0. } else { delta_movement.z },
@ -213,7 +213,7 @@ pub fn move_colliding(
// blockBelow.updateEntityAfterFallOn(this.level, this);
// the default implementation of updateEntityAfterFallOn sets the y movement to
// 0
physics.delta.y = 0.;
physics.velocity.y = 0.;
}
if on_ground {

View file

@ -113,9 +113,9 @@ fn travel(
// if should_discard_friction(self) {
if false {
physics.delta = movement;
physics.velocity = movement;
} else {
physics.delta = Vec3 {
physics.velocity = Vec3 {
x: movement.x * inertia as f64,
y: movement.y * 0.9800000190734863f64,
z: movement.z * inertia as f64,
@ -145,14 +145,14 @@ pub fn ai_step(
// vanilla does movement interpolation here, doesn't really matter much for a
// bot though
if physics.delta.x.abs() < 0.003 {
physics.delta.x = 0.;
if physics.velocity.x.abs() < 0.003 {
physics.velocity.x = 0.;
}
if physics.delta.y.abs() < 0.003 {
physics.delta.y = 0.;
if physics.velocity.y.abs() < 0.003 {
physics.velocity.y = 0.;
}
if physics.delta.z.abs() < 0.003 {
physics.delta.z = 0.;
if physics.velocity.z.abs() < 0.003 {
physics.velocity.z = 0.;
}
if let Some(jumping) = jumping {
@ -194,8 +194,8 @@ pub fn jump_from_ground(
let world = world_lock.read();
let jump_power: f64 = jump_power(&world, position) as f64 + jump_boost_power();
let old_delta_movement = physics.delta;
physics.delta = Vec3 {
let old_delta_movement = physics.velocity;
physics.velocity = Vec3 {
x: old_delta_movement.x,
y: jump_power,
z: old_delta_movement.z,
@ -203,7 +203,7 @@ pub fn jump_from_ground(
if **sprinting {
// sprint jumping gives some extra velocity
let y_rot = look_direction.y_rot * 0.017453292;
physics.delta += Vec3 {
physics.velocity += Vec3 {
x: (-math::sin(y_rot) * 0.2) as f64,
y: 0.,
z: (math::cos(y_rot) * 0.2) as f64,
@ -245,7 +245,7 @@ fn handle_relative_friction_and_calculate_movement(
// entity.delta = entity.handle_on_climbable(entity.delta);
move_colliding(
&MoverType::Own,
&physics.delta.clone(),
&physics.velocity.clone(),
world,
position,
physics,
@ -259,7 +259,7 @@ fn handle_relative_friction_and_calculate_movement(
// Vec3(var3.x, 0.2D, var3.z); }
// TODO: powdered snow
physics.delta
physics.velocity
}
// private float getFrictionInfluencedSpeed(float friction) {
@ -400,7 +400,7 @@ mod tests {
// delta is applied before gravity, so the first tick only sets the delta
assert_eq!(entity_pos.y, 70.);
let entity_physics = app.world.get::<Physics>(entity).unwrap();
assert!(entity_physics.delta.y < 0.);
assert!(entity_physics.velocity.y < 0.);
}
app.world.run_schedule(FixedUpdate);
app.update();
@ -463,7 +463,7 @@ mod tests {
// delta will change, but it won't move until next tick
assert_eq!(entity_pos.y, 70.);
let entity_physics = app.world.get::<Physics>(entity).unwrap();
assert!(entity_physics.delta.y < 0.);
assert!(entity_physics.velocity.y < 0.);
}
app.world.run_schedule(FixedUpdate);
app.update();

View file

@ -1,13 +1,12 @@
use azalea_brigadier::suggestion::Suggestions;
use azalea_buf::McBuf;
use azalea_chat::FormattedText;
use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundCommandSuggestionsPacket {
#[var]
pub id: u32,
pub suggestions: Suggestions<FormattedText>,
pub suggestions: Suggestions,
}
#[cfg(test)]
@ -24,7 +23,7 @@ mod tests {
vec![Suggestion::new_with_tooltip(
StringRange::new(1, 4),
"foo",
FormattedText::from("bar".to_string()),
"bar".to_string(),
)],
);
let mut buf = Vec::new();

View file

@ -35,7 +35,7 @@ pub fn best_tool_in_hotbar_for_block(block: BlockState, menu: &Menu) -> BestTool
menu,
&Physics {
on_ground: true,
delta: Default::default(),
velocity: Default::default(),
xxa: Default::default(),
yya: Default::default(),
zza: Default::default(),

View file

@ -25,7 +25,7 @@ use crate::pathfinder::moves::PathfinderCtx;
use crate::pathfinder::world::CachedWorld;
use azalea_client::chat::SendChatEvent;
use azalea_client::inventory::{InventoryComponent, InventorySet};
use azalea_client::movement::walk_listener;
use azalea_client::movement::MoveEventsSet;
use azalea_client::{StartSprintEvent, StartWalkEvent};
use azalea_core::position::{BlockPos, Vec3};
use azalea_entity::metadata::Player;
@ -85,7 +85,7 @@ impl Plugin for PathfinderPlugin {
handle_stop_pathfinding_event,
)
.chain()
.before(walk_listener)
.before(MoveEventsSet)
.before(InventorySet),
);
}
@ -462,8 +462,8 @@ fn check_node_reached(
&& BlockPos::from(position) == movement.target
// adding the delta like this isn't a perfect solution but it helps to make
// sure we don't keep going if our delta is high
&& (x_difference_from_center + physics.delta.x).abs() < 0.2
&& (z_difference_from_center + physics.delta.z).abs() < 0.2
&& (x_difference_from_center + physics.velocity.x).abs() < 0.2
&& (z_difference_from_center + physics.velocity.z).abs() < 0.2
} else {
true
};

View file

@ -97,7 +97,7 @@ fn execute_ascend_move(mut ctx: ExecuteCtx) {
let side_distance = z_axis as f64 * (target_center.x - position.x).abs()
+ x_axis as f64 * (target_center.z - position.z).abs();
let lateral_motion = x_axis as f64 * physics.delta.z + z_axis as f64 * physics.delta.x;
let lateral_motion = x_axis as f64 * physics.velocity.z + z_axis as f64 * physics.velocity.x;
if lateral_motion > 0.1 {
return;
}