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

make physicsstate its own component

This commit is contained in:
Ubuntu 2023-01-12 02:24:18 +00:00
parent 1b83277a0c
commit 473b9f9297
5 changed files with 141 additions and 104 deletions

View file

@ -1,6 +1,6 @@
pub use crate::chat::ChatPacket;
use crate::{
local_player::{death_event, send_tick_event, update_in_loaded_chunk, LocalPlayer},
local_player::{death_event, send_tick_event, update_in_loaded_chunk, LocalPlayer, PhysicsState},
movement::{local_player_ai_step, send_position},
packet_handling,
plugins::PluginStates,
@ -223,7 +223,7 @@ impl Client {
local_player.tasks.push(write_packets_task);
ecs.entity_mut(entity)
.insert((local_player, packet_receiver));
.insert((local_player, packet_receiver, PhysicsState::default()));
// just start up the game loop and we're ready!

View file

@ -22,8 +22,6 @@ pub struct LocalPlayer {
pub packet_writer: mpsc::UnboundedSender<ServerboundGamePacket>,
// pub world: Arc<RwLock<PartialWorld>>,
pub physics_state: PhysicsState,
pub client_information: ClientInformation,
/// A map of player uuids to their information in the tab list
pub players: HashMap<Uuid, PlayerInfo>,
@ -43,7 +41,9 @@ pub struct LocalPlayer {
pub(crate) tasks: Vec<JoinHandle<()>>,
}
#[derive(Default)]
/// Component for entities that can move and sprint. Usually only in
/// [`LocalPlayer`] entities.
#[derive(Default, Component)]
pub struct PhysicsState {
/// Minecraft only sends a movement packet either after 20 ticks or if the
/// player moved enough. This is that tick counter.
@ -83,7 +83,6 @@ impl LocalPlayer {
packet_writer,
physics_state: PhysicsState::default(),
client_information: ClientInformation::default(),
players: HashMap::new(),

View file

@ -7,7 +7,8 @@ use azalea_protocol::packets::game::{
serverbound_move_player_rot_packet::ServerboundMovePlayerRotPacket,
serverbound_move_player_status_only_packet::ServerboundMovePlayerStatusOnlyPacket,
};
use azalea_world::entity::MinecraftEntityId;
use azalea_world::entity::metadata::Sprinting;
use azalea_world::entity::{Attributes, MinecraftEntityId};
use azalea_world::{entity, MoveEntityError};
use bevy_ecs::system::Query;
use std::backtrace::Backtrace;
@ -39,7 +40,7 @@ impl Client {
/// recommended.
pub fn set_jumping(&mut self, jumping: bool) {
let mut ecs = self.ecs.lock();
let mut physics = self.query::<&mut entity::Physics>(&mut ecs).into_inner();
let mut physics = self.query::<&mut entity::Physics>(&mut ecs);
physics.jumping = jumping;
}
@ -67,6 +68,7 @@ pub(crate) fn send_position(
(
&MinecraftEntityId,
&mut LocalPlayer,
&mut PhysicsState,
&entity::Position,
&mut entity::LastSentPosition,
&mut entity::Physics,
@ -75,10 +77,17 @@ pub(crate) fn send_position(
&LocalPlayerInLoadedChunk,
>,
) {
for (id, mut local_player, position, mut last_sent_position, mut physics, sprinting) in
query.iter_mut()
for (
id,
mut local_player,
mut physics_state,
position,
mut last_sent_position,
mut physics,
sprinting,
) in query.iter_mut()
{
local_player.send_sprinting_if_needed(id, sprinting);
local_player.send_sprinting_if_needed(id, sprinting, &mut physics_state);
let packet = {
// TODO: the camera being able to be controlled by other entities isn't
@ -90,13 +99,13 @@ pub(crate) fn send_position(
let y_rot_delta = (physics.y_rot - physics.y_rot_last) as f64;
let x_rot_delta = (physics.x_rot - physics.x_rot_last) as f64;
local_player.physics_state.position_remainder += 1;
physics_state.position_remainder += 1;
// boolean sendingPosition = Mth.lengthSquared(xDelta, yDelta, zDelta) >
// Mth.square(2.0E-4D) || this.positionReminder >= 20;
let sending_position = ((x_delta.powi(2) + y_delta.powi(2) + z_delta.powi(2))
> 2.0e-4f64.powi(2))
|| local_player.physics_state.position_remainder >= 20;
|| physics_state.position_remainder >= 20;
let sending_rotation = y_rot_delta != 0.0 || x_rot_delta != 0.0;
// if self.is_passenger() {
@ -146,7 +155,7 @@ pub(crate) fn send_position(
if sending_position {
**last_sent_position = **position;
local_player.physics_state.position_remainder = 0;
physics_state.position_remainder = 0;
}
if sending_rotation {
physics.y_rot_last = physics.y_rot;
@ -170,8 +179,9 @@ impl LocalPlayer {
&mut self,
id: &MinecraftEntityId,
sprinting: &entity::metadata::Sprinting,
physics_state: &mut PhysicsState,
) {
let was_sprinting = self.physics_state.was_sprinting;
let was_sprinting = physics_state.was_sprinting;
if **sprinting != was_sprinting {
let sprinting_action = if **sprinting {
azalea_protocol::packets::game::serverbound_player_command_packet::Action::StartSprinting
@ -186,7 +196,7 @@ impl LocalPlayer {
}
.get(),
);
self.physics_state.was_sprinting = **sprinting;
physics_state.was_sprinting = **sprinting;
}
}
@ -224,84 +234,6 @@ impl LocalPlayer {
physics_state.left_impulse *= multiplier;
}
}
/// Start walking in the given direction. To sprint, use
/// [`Client::sprint`]. To stop walking, call walk with
/// `WalkDirection::None`.
///
/// # Examples
///
/// Walk for 1 second
/// ```rust,no_run
/// # use azalea_client::{Client, WalkDirection};
/// # use std::time::Duration;
/// # async fn example(mut bot: Client) {
/// bot.walk(WalkDirection::Forward);
/// tokio::time::sleep(Duration::from_secs(1)).await;
/// bot.walk(WalkDirection::None);
/// # }
/// ```
pub fn walk(
direction: WalkDirection,
physics_state: &mut PhysicsState,
sprinting: &mut entity::metadata::Sprinting,
attributes: &mut entity::Attributes,
) {
physics_state.move_direction = direction;
Self::set_sprinting(false, sprinting, attributes);
}
/// Start sprinting in the given direction. To stop moving, call
/// [`Client::walk(WalkDirection::None)`]
///
/// # Examples
///
/// Sprint for 1 second
/// ```rust,no_run
/// # use azalea_client::{Client, WalkDirection, SprintDirection};
/// # use std::time::Duration;
/// # async fn example(mut bot: Client) {
/// bot.sprint(SprintDirection::Forward);
/// tokio::time::sleep(Duration::from_secs(1)).await;
/// bot.walk(WalkDirection::None);
/// # }
/// ```
pub fn sprint(&mut self, direction: SprintDirection, physics_state: &mut PhysicsState) {
physics_state.move_direction = WalkDirection::from(direction);
physics_state.trying_to_sprint = true;
}
/// Change whether we're sprinting by adding an attribute modifier to the
/// player. You should use the [`walk`] and [`sprint`] methods instead.
/// Returns if the operation was successful.
fn set_sprinting(
sprinting: bool,
currently_sprinting: &mut entity::metadata::Sprinting,
attributes: &mut entity::Attributes,
) -> bool {
**currently_sprinting = sprinting;
if sprinting {
attributes
.speed
.insert(entity::attributes::sprinting_modifier())
.is_ok()
} else {
attributes
.speed
.remove(&entity::attributes::sprinting_modifier().uuid)
.is_none()
}
}
// Whether the player is moving fast enough to be able to start sprinting.
fn has_enough_impulse_to_start_sprinting(physics_state: &PhysicsState) -> bool {
// if self.underwater() {
// self.has_forward_impulse()
// } else {
physics_state.forward_impulse > 0.8
// }
}
}
/// Makes the bot do one physics tick. Note that this is already handled
@ -310,6 +242,7 @@ pub fn local_player_ai_step(
mut query: Query<
(
&mut LocalPlayer,
&mut PhysicsState,
&mut entity::Physics,
&mut entity::Position,
&mut entity::metadata::Sprinting,
@ -319,12 +252,16 @@ pub fn local_player_ai_step(
>,
) {
println!("local_player_ai_step");
for (mut local_player, mut physics, mut position, mut sprinting, mut attributes) in
query.iter_mut()
for (
local_player,
mut physics_state,
mut physics,
mut position,
mut sprinting,
mut attributes,
) in query.iter_mut()
{
let physics_state = &mut local_player.physics_state;
LocalPlayer::tick_controls(None, physics_state);
LocalPlayer::tick_controls(None, &mut physics_state);
// server ai step
physics.xxa = physics_state.left_impulse;
@ -343,14 +280,14 @@ pub fn local_player_ai_step(
&& (
// !self.is_in_water()
// || self.is_underwater() &&
LocalPlayer::has_enough_impulse_to_start_sprinting(physics_state)
has_enough_impulse_to_start_sprinting(&physics_state)
&& has_enough_food_to_sprint
// && !self.using_item()
// && !self.has_effect(MobEffects.BLINDNESS)
&& trying_to_sprint
)
{
LocalPlayer::set_sprinting(true, &mut sprinting, &mut attributes);
set_sprinting(true, &mut sprinting, &mut attributes);
}
azalea_physics::ai_step(
@ -363,6 +300,107 @@ pub fn local_player_ai_step(
}
}
impl Client {
/// Start walking in the given direction. To sprint, use
/// [`Client::sprint`]. To stop walking, call walk with
/// `WalkDirection::None`.
///
/// # Examples
///
/// Walk for 1 second
/// ```rust,no_run
/// # use azalea_client::{Client, WalkDirection};
/// # use std::time::Duration;
/// # async fn example(mut bot: Client) {
/// bot.walk(WalkDirection::Forward);
/// tokio::time::sleep(Duration::from_secs(1)).await;
/// bot.walk(WalkDirection::None);
/// # }
/// ```
pub fn walk(&mut self, direction: WalkDirection) {
let mut ecs = self.ecs.lock();
let (mut physics_state, mut sprinting, mut attributes) =
self.query::<(&mut PhysicsState, &mut Sprinting, &mut Attributes)>(&mut ecs);
walk(
direction,
&mut physics_state,
&mut sprinting,
&mut attributes,
)
}
/// Start sprinting in the given direction. To stop moving, call
/// [`Client::walk(WalkDirection::None)`]
///
/// # Examples
///
/// Sprint for 1 second
/// ```rust,no_run
/// # use azalea_client::{Client, WalkDirection, SprintDirection};
/// # use std::time::Duration;
/// # async fn example(mut bot: Client) {
/// bot.sprint(SprintDirection::Forward);
/// tokio::time::sleep(Duration::from_secs(1)).await;
/// bot.walk(WalkDirection::None);
/// # }
/// ```
pub fn sprint(&mut self, direction: SprintDirection) {
let mut ecs = self.ecs.lock();
let mut physics_state = self.query::<&mut PhysicsState>(&mut ecs);
sprint(direction, &mut physics_state);
}
}
/// Start walking in the given direction. To sprint, use
/// [`Client::sprint`]. To stop walking, call walk with
/// `WalkDirection::None`.
pub fn walk(
direction: WalkDirection,
physics_state: &mut PhysicsState,
sprinting: &mut entity::metadata::Sprinting,
attributes: &mut entity::Attributes,
) {
physics_state.move_direction = direction;
set_sprinting(false, sprinting, attributes);
}
/// Start sprinting in the given direction.
pub fn sprint(direction: SprintDirection, physics_state: &mut PhysicsState) {
physics_state.move_direction = WalkDirection::from(direction);
physics_state.trying_to_sprint = true;
}
/// Change whether we're sprinting by adding an attribute modifier to the
/// player. You should use the [`walk`] and [`sprint`] methods instead.
/// Returns if the operation was successful.
fn set_sprinting(
sprinting: bool,
currently_sprinting: &mut entity::metadata::Sprinting,
attributes: &mut entity::Attributes,
) -> bool {
**currently_sprinting = sprinting;
if sprinting {
attributes
.speed
.insert(entity::attributes::sprinting_modifier())
.is_ok()
} else {
attributes
.speed
.remove(&entity::attributes::sprinting_modifier().uuid)
.is_none()
}
}
// Whether the player is moving fast enough to be able to start sprinting.
fn has_enough_impulse_to_start_sprinting(physics_state: &PhysicsState) -> bool {
// if self.underwater() {
// self.has_forward_impulse()
// } else {
physics_state.forward_impulse > 0.8
// }
}
#[derive(Clone, Copy, Debug, Default)]
pub enum WalkDirection {
#[default]

View file

@ -61,7 +61,7 @@ fn handle_packets(
mut mut_local_player_query: Query<&mut LocalPlayer>,
mut mut_health_query: Query<&mut Health>,
mut mut_position_query: Query<&mut Position>,
combat_kill_query: Query<(&MinecraftEntityId, Option<&Dead>)>,
mut position_query: Query<(
&mut LocalPlayer,
@ -279,7 +279,7 @@ fn handle_packets(
// we call a function instead of setting the fields ourself since the
// function makes sure the rotations stay in their
// ranges
set_rotation(physics.into_inner(), y_rot, x_rot);
set_rotation(&mut physics, y_rot, x_rot);
// TODO: minecraft sets "xo", "yo", and "zo" here but idk what that means
// so investigate that ig
let new_pos = Vec3 {

View file

@ -432,7 +432,7 @@ where
/// }
/// ```
fn into_iter(self) -> Self::IntoIter {
self.bot_datas.lock().clone().into_iter()
self.bot_datas.clone().lock().into_iter()
}
}