From 9ca95194696f8e9ef3ca84420f5d3b5082ff70ca Mon Sep 17 00:00:00 2001 From: mat Date: Mon, 5 Sep 2022 01:04:16 -0500 Subject: [PATCH] .walk :) --- Cargo.lock | 1 + azalea-chat/src/component.rs | 30 +++++++- azalea-client/Cargo.toml | 1 + azalea-client/src/client.rs | 34 +++++---- azalea-client/src/lib.rs | 1 + azalea-client/src/movement.rs | 71 +++++++++++++++++-- azalea-physics/src/lib.rs | 1 + .../game/clientbound_player_chat_packet.rs | 14 ++++ bot/src/main.rs | 31 +++++++- 9 files changed, 164 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed2026b2..a443ce56 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,6 +156,7 @@ dependencies = [ "anyhow", "azalea-auth", "azalea-block", + "azalea-chat", "azalea-core", "azalea-crypto", "azalea-physics", diff --git a/azalea-chat/src/component.rs b/azalea-chat/src/component.rs index 9c71b9df..59b1779e 100755 --- a/azalea-chat/src/component.rs +++ b/azalea-chat/src/component.rs @@ -1,4 +1,7 @@ -use std::io::{Read, Write}; +use std::{ + fmt::Display, + io::{Read, Write}, +}; use azalea_buf::{BufReadError, McBufReadable, McBufWritable}; use serde::{de, Deserialize, Deserializer}; @@ -293,3 +296,28 @@ impl McBufWritable for Component { todo!() } } + +impl From for Component { + fn from(s: String) -> Self { + Component::Text(TextComponent { + text: s, + base: BaseComponent::default(), + }) + } +} + +impl Display for Component { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // this contains the final string will all the ansi escape codes + for component in self.clone().into_iter() { + let component_text = match &component { + Self::Text(c) => c.text.to_string(), + Self::Translatable(c) => c.to_string(), + }; + + f.write_str(&component_text)?; + } + + Ok(()) + } +} diff --git a/azalea-client/Cargo.toml b/azalea-client/Cargo.toml index 8efa09b3..e69da668 100755 --- a/azalea-client/Cargo.toml +++ b/azalea-client/Cargo.toml @@ -9,6 +9,7 @@ version = "0.1.0" anyhow = "1.0.59" azalea-auth = {path = "../azalea-auth"} azalea-block = {path = "../azalea-block"} +azalea-chat = {path = "../azalea-chat"} azalea-core = {path = "../azalea-core"} azalea-crypto = {path = "../azalea-crypto"} azalea-physics = {path = "../azalea-physics"} diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 1e05ca9e..9d9675b8 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -1,6 +1,7 @@ -use crate::{Account, Player}; +use crate::{movement::MoveDirection, Account, Player}; use azalea_auth::game_profile::GameProfile; use azalea_block::BlockState; +use azalea_chat::component::Component; use azalea_core::{ChunkPos, ResourceLocation, Vec3}; use azalea_protocol::{ connect::{Connection, ConnectionError}, @@ -52,14 +53,14 @@ pub enum ChatPacket { Player(Box), } -// impl ChatPacket { -// pub fn message(&self) -> &str { -// match self { -// ChatPacket::System(p) => &p.content, -// ChatPacket::Player(p) => &p.message, -// } -// } -// } +impl ChatPacket { + pub fn message(&self) -> Component { + match self { + ChatPacket::System(p) => p.content.clone(), + ChatPacket::Player(p) => p.message.message(false), + } + } +} /// A player that you can control that is currently in a Minecraft server. #[derive(Clone)] @@ -68,9 +69,17 @@ pub struct Client { pub conn: Arc>>, pub player: Arc>, pub dimension: Arc>, + pub physics_state: Arc>, +} +#[derive(Default)] +pub struct PhysicsState { /// Minecraft only sends a movement packet either after 20 ticks or if the player moved enough. This is that tick counter. pub position_remainder: u32, + + pub move_direction: MoveDirection, + pub forward_impulse: f32, + pub left_impulse: f32, } /// Whether we should ignore errors when decoding packets. @@ -185,8 +194,7 @@ impl Client { conn, player: Arc::new(Mutex::new(Player::default())), dimension: Arc::new(Mutex::new(Dimension::default())), - - position_remainder: 0, + physics_state: Arc::new(Mutex::new(PhysicsState::default())), }; // just start up the game loop and we're ready! @@ -552,8 +560,8 @@ impl Client { .move_entity_with_delta(p.entity_id, &p.delta) .map_err(|e| HandleError::Other(e.into()))?; } - ClientboundGamePacket::ClientboundMoveEntityRotPacket(p) => { - println!("Got move entity rot packet {:?}", p); + ClientboundGamePacket::ClientboundMoveEntityRotPacket(_p) => { + // println!("Got move entity rot packet {:?}", p); } ClientboundGamePacket::ClientboundKeepAlivePacket(p) => { println!("Got keep alive packet {:?}", p); diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs index c3c37460..a918ca32 100755 --- a/azalea-client/src/lib.rs +++ b/azalea-client/src/lib.rs @@ -8,6 +8,7 @@ mod player; pub use account::Account; pub use client::{Client, Event}; +pub use movement::MoveDirection; pub use player::Player; #[cfg(test)] diff --git a/azalea-client/src/movement.rs b/azalea-client/src/movement.rs index df2af9d8..ddc44c0a 100644 --- a/azalea-client/src/movement.rs +++ b/azalea-client/src/movement.rs @@ -32,7 +32,7 @@ impl Client { pub async fn send_position(&mut self) -> Result<(), MovePlayerError> { let packet = { let player_lock = self.player.lock().unwrap(); - + let mut physics_state = self.physics_state.lock().unwrap(); let mut dimension_lock = self.dimension.lock().unwrap(); let mut player_entity = player_lock @@ -52,12 +52,12 @@ impl Client { let y_rot_delta = (player_entity.y_rot - player_entity.y_rot_last) as f64; let x_rot_delta = (player_entity.x_rot - player_entity.x_rot_last) as f64; - self.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)) - || self.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() { @@ -107,7 +107,7 @@ impl Client { if sending_position { player_entity.last_pos = *player_entity.pos(); - self.position_remainder = 0; + physics_state.position_remainder = 0; } if sending_rotation { player_entity.y_rot_last = player_entity.y_rot; @@ -155,6 +155,8 @@ impl Client { } pub fn ai_step(&mut self) { + self.tick_controls(None); + let player_lock = self.player.lock().unwrap(); let mut dimension_lock = self.dimension.lock().unwrap(); @@ -162,6 +164,67 @@ impl Client { .entity_mut(&mut dimension_lock) .expect("Player must exist"); + // server ai step + { + let physics_state = self.physics_state.lock().unwrap(); + player_entity.xxa = physics_state.left_impulse; + player_entity.zza = physics_state.forward_impulse; + } + player_entity.ai_step(); } + + /// Update the impulse from self.move_direction. The multipler is used for sneaking. + pub(crate) fn tick_controls(&mut self, multiplier: Option) { + let mut physics_state = self.physics_state.lock().unwrap(); + + let mut forward_impulse: f32 = 0.; + let mut left_impulse: f32 = 0.; + match physics_state.move_direction { + MoveDirection::Forward | MoveDirection::ForwardRight | MoveDirection::ForwardLeft => { + forward_impulse += 1.; + } + MoveDirection::Backward + | MoveDirection::BackwardRight + | MoveDirection::BackwardLeft => { + forward_impulse -= 1.; + } + _ => {} + }; + match physics_state.move_direction { + MoveDirection::Right | MoveDirection::ForwardRight | MoveDirection::BackwardRight => { + left_impulse += 1.; + } + MoveDirection::Left | MoveDirection::ForwardLeft | MoveDirection::BackwardLeft => { + left_impulse -= 1.; + } + _ => {} + }; + physics_state.forward_impulse = forward_impulse; + physics_state.left_impulse = left_impulse; + + if let Some(multiplier) = multiplier { + physics_state.forward_impulse *= multiplier; + physics_state.left_impulse *= multiplier; + } + } + + pub fn walk(&mut self, direction: MoveDirection) { + let mut physics_state = self.physics_state.lock().unwrap(); + physics_state.move_direction = direction; + } +} + +#[derive(Clone, Copy, Debug, Default)] +pub enum MoveDirection { + #[default] + None, + Forward, + Backward, + Left, + Right, + ForwardRight, + ForwardLeft, + BackwardRight, + BackwardLeft, } diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 8f9c256e..f80d1bad 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -81,6 +81,7 @@ impl HasPhysics for EntityMut<'_> { if self.delta.z.abs() < 0.003 { self.delta.z = 0.; } + self.xxa *= 0.98; self.zza *= 0.98; diff --git a/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs b/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs index 492f352f..6b4582ba 100644 --- a/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs @@ -49,6 +49,20 @@ pub struct SignedMessageBody { pub last_seen: Vec, } +impl PlayerChatMessage { + pub fn message(&self, only_secure_chat: bool) -> Component { + if only_secure_chat { + return self + .signed_body + .content + .decorated + .clone() + .unwrap_or(Component::from(self.signed_body.content.plain.clone())); + } + self.unsigned_content.clone().unwrap_or(self.message(true)) + } +} + #[derive(Clone, Debug, McBuf)] pub struct LastSeenMessagesEntry { pub profile_id: Uuid, diff --git a/bot/src/main.rs b/bot/src/main.rs index 0b49f30b..f9977d99 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -1,5 +1,5 @@ #![allow(unused_variables, unused_imports)] -use azalea_client::{Account, Event}; +use azalea_client::{Account, Event, MoveDirection}; use azalea_core::{PositionXYZ, Vec3}; use azalea_physics::collision::{HasCollision, MoverType}; @@ -15,7 +15,7 @@ async fn main() -> Result<(), Box> { // println!("{}", response.description.to_ansi(None)); let account = Account::offline("bot"); - let (client, mut rx) = account.join(&address.try_into().unwrap()).await.unwrap(); + let (mut client, mut rx) = account.join(&address.try_into().unwrap()).await.unwrap(); println!("connected"); while let Some(e) = &rx.recv().await { @@ -41,6 +41,33 @@ async fn main() -> Result<(), Box> { // // } // } Event::Chat(m) => { + let message = m.message().to_string(); + println!("{}", message); + + match &message[..] { + "stop" => { + println!("stopping"); + client.walk(MoveDirection::None); + } + "forward" => { + println!("moving forward"); + client.walk(MoveDirection::Forward); + } + "backward" => { + println!("moving backward"); + client.walk(MoveDirection::Backward); + } + "left" => { + println!("moving left"); + client.walk(MoveDirection::Left); + } + "right" => { + println!("moving right"); + client.walk(MoveDirection::Right); + } + _ => {} + } + // let new_pos = { // let dimension_lock = client.dimension.lock().unwrap(); // let player = client.player.lock().unwrap();