diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2022-10-07 19:57:42 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-07 19:57:42 -0500 |
| commit | ba4cfaafaec97a3c5b9405fe542035ebe9039edd (patch) | |
| tree | 5fc7340a49f96d84f86ed6adf400ad461c47d1b6 /azalea-client | |
| parent | e0bcab53b8a3721a008e47062c6b5972fa64b8ad (diff) | |
| download | azalea-drasl-ba4cfaafaec97a3c5b9405fe542035ebe9039edd.tar.xz | |
Bot API (#27)
Basically make the `azalea` crate have stuff
Diffstat (limited to 'azalea-client')
| -rwxr-xr-x | azalea-client/Cargo.toml | 1 | ||||
| -rw-r--r-- | azalea-client/src/client.rs | 72 | ||||
| -rw-r--r-- | azalea-client/src/movement.rs | 54 |
3 files changed, 70 insertions, 57 deletions
diff --git a/azalea-client/Cargo.toml b/azalea-client/Cargo.toml index 66e5ca42..bbcf732b 100755 --- a/azalea-client/Cargo.toml +++ b/azalea-client/Cargo.toml @@ -16,6 +16,7 @@ azalea-physics = {path = "../azalea-physics"} azalea-protocol = {path = "../azalea-protocol"} azalea-world = {path = "../azalea-world"} log = "0.4.17" +parking_lot = "0.12.1" thiserror = "^1.0.34" tokio = {version = "^1.19.2", features = ["sync"]} uuid = "^1.1.2" diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 2b721206..d5071787 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -25,14 +25,13 @@ use azalea_protocol::{ read::ReadPacketError, resolver, ServerAddress, }; -use azalea_world::entity::EntityData; -use azalea_world::Dimension; -use log::{debug, error, warn}; -use std::{ - fmt::Debug, - io, - sync::{Arc, Mutex}, +use azalea_world::{ + entity::{EntityData, EntityMut, EntityRef}, + Dimension, }; +use log::{debug, error, warn}; +use parking_lot::Mutex; +use std::{fmt::Debug, io, sync::Arc}; use thiserror::Error; use tokio::{ io::AsyncWriteExt, @@ -41,12 +40,14 @@ use tokio::{ time::{self}, }; +/// Events are sent before they're processed, so for example game ticks happen +/// at the beginning of a tick before anything has happened. #[derive(Debug, Clone)] pub enum Event { Login, Chat(ChatPacket), /// A game tick, happens 20 times per second. - GameTick, + Tick, Packet(Box<ClientboundGamePacket>), } @@ -219,7 +220,7 @@ impl Client { // read the error to see where the issue is // you might be able to just drop the lock or put it in its own scope to fix { - let mut tasks = client.tasks.lock().unwrap(); + let mut tasks = client.tasks.lock(); tasks.push(tokio::spawn(Self::protocol_loop( client.clone(), tx.clone(), @@ -238,7 +239,7 @@ impl Client { /// Disconnect from the server, ending all tasks. pub async fn shutdown(self) -> Result<(), std::io::Error> { self.write_conn.lock().await.write_stream.shutdown().await?; - let tasks = self.tasks.lock().unwrap(); + let tasks = self.tasks.lock(); for task in tasks.iter() { task.abort(); } @@ -346,7 +347,7 @@ impl Client { .as_int() .expect("min_y tag is not an int"); - let mut dimension_lock = client.dimension.lock().unwrap(); + let mut dimension_lock = client.dimension.lock(); // the 16 here is our render distance // i'll make this an actual setting later *dimension_lock = Dimension::new(16, height, min_y); @@ -354,7 +355,7 @@ impl Client { let entity = EntityData::new(client.game_profile.uuid, Vec3::default()); dimension_lock.add_entity(p.player_id, entity); - let mut player_lock = client.player.lock().unwrap(); + let mut player_lock = client.player.lock(); player_lock.set_entity_id(p.player_id); } @@ -411,11 +412,11 @@ impl Client { let (new_pos, y_rot, x_rot) = { let player_entity_id = { - let player_lock = client.player.lock().unwrap(); + let player_lock = client.player.lock(); player_lock.entity_id }; - let mut dimension_lock = client.dimension.lock().unwrap(); + let mut dimension_lock = client.dimension.lock(); let mut player_entity = dimension_lock .entity_mut(player_entity_id) @@ -503,7 +504,7 @@ impl Client { debug!("Got chunk cache center packet {:?}", p); client .dimension - .lock()? + .lock() .update_view_center(&ChunkPos::new(p.x, p.z)); } ClientboundGamePacket::LevelChunkWithLight(p) => { @@ -513,7 +514,7 @@ impl Client { // debug("chunk {:?}") client .dimension - .lock()? + .lock() .replace_with_packet_data(&pos, &mut p.chunk_data.data.as_slice()) .unwrap(); } @@ -523,7 +524,7 @@ impl Client { ClientboundGamePacket::AddEntity(p) => { debug!("Got add entity packet {:?}", p); let entity = EntityData::from(p); - client.dimension.lock()?.add_entity(p.id, entity); + client.dimension.lock().add_entity(p.id, entity); } ClientboundGamePacket::SetEntityData(_p) => { // debug!("Got set entity data packet {:?}", p); @@ -540,7 +541,7 @@ impl Client { ClientboundGamePacket::AddPlayer(p) => { debug!("Got add player packet {:?}", p); let entity = EntityData::from(p); - client.dimension.lock()?.add_entity(p.id, entity); + client.dimension.lock().add_entity(p.id, entity); } ClientboundGamePacket::InitializeBorder(p) => { debug!("Got initialize border packet {:?}", p); @@ -561,7 +562,7 @@ impl Client { debug!("Got set experience packet {:?}", p); } ClientboundGamePacket::TeleportEntity(p) => { - let mut dimension_lock = client.dimension.lock()?; + let mut dimension_lock = client.dimension.lock(); dimension_lock .set_entity_pos( @@ -581,14 +582,14 @@ impl Client { // debug!("Got rotate head packet {:?}", p); } ClientboundGamePacket::MoveEntityPos(p) => { - let mut dimension_lock = client.dimension.lock()?; + let mut dimension_lock = client.dimension.lock(); dimension_lock .move_entity_with_delta(p.entity_id, &p.delta) .map_err(|e| HandleError::Other(e.into()))?; } ClientboundGamePacket::MoveEntityPosRot(p) => { - let mut dimension_lock = client.dimension.lock()?; + let mut dimension_lock = client.dimension.lock(); dimension_lock .move_entity_with_delta(p.entity_id, &p.delta) @@ -623,7 +624,7 @@ impl Client { } ClientboundGamePacket::BlockUpdate(p) => { debug!("Got block update packet {:?}", p); - let mut dimension = client.dimension.lock()?; + let mut dimension = client.dimension.lock(); dimension.set_block_state(&p.pos, p.block_state); } ClientboundGamePacket::Animate(p) => { @@ -725,10 +726,12 @@ impl Client { /// Runs every 50 milliseconds. async fn game_tick(client: &mut Client, tx: &UnboundedSender<Event>) { + tx.send(Event::Tick).unwrap(); + // return if there's no chunk at the player's position { - let dimension_lock = client.dimension.lock().unwrap(); - let player_lock = client.player.lock().unwrap(); + let dimension_lock = client.dimension.lock(); + let player_lock = client.player.lock(); let player_entity = player_lock.entity(&dimension_lock); let player_entity = if let Some(player_entity) = player_entity { player_entity @@ -749,8 +752,27 @@ impl Client { client.ai_step(); // TODO: minecraft does ambient sounds here + } - tx.send(Event::GameTick).unwrap(); + /// Returns the entity associated to the player. + pub fn entity_mut<'d>(&self, dimension: &'d mut Dimension) -> EntityMut<'d> { + let entity_id = { + let player_lock = self.player.lock(); + player_lock.entity_id + }; + dimension + .entity_mut(entity_id) + .expect("Player entity should be in the given dimension") + } + /// Returns the entity associated to the player. + pub fn entity<'d>(&self, dimension: &'d Dimension) -> EntityRef<'d> { + let entity_id = { + let player_lock = self.player.lock(); + player_lock.entity_id + }; + dimension + .entity(entity_id) + .expect("Player entity should be in the given dimension") } } diff --git a/azalea-client/src/movement.rs b/azalea-client/src/movement.rs index ab324370..fb4a5968 100644 --- a/azalea-client/src/movement.rs +++ b/azalea-client/src/movement.rs @@ -31,9 +31,9 @@ impl Client { /// This gets called every tick. 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 player_lock = self.player.lock(); + let mut physics_state = self.physics_state.lock(); + let mut dimension_lock = self.dimension.lock(); let mut player_entity = player_lock .entity_mut(&mut dimension_lock) @@ -129,8 +129,8 @@ impl Client { // Set our current position to the provided Vec3, potentially clipping through blocks. pub async fn set_pos(&mut self, new_pos: Vec3) -> Result<(), MovePlayerError> { - let player_lock = self.player.lock().unwrap(); - let mut dimension_lock = self.dimension.lock().unwrap(); + let player_lock = self.player.lock(); + let mut dimension_lock = self.dimension.lock(); dimension_lock.set_entity_pos(player_lock.entity_id, new_pos)?; @@ -138,8 +138,8 @@ impl Client { } pub async fn move_entity(&mut self, movement: &Vec3) -> Result<(), MovePlayerError> { - let mut dimension_lock = self.dimension.lock().unwrap(); - let player = self.player.lock().unwrap(); + let mut dimension_lock = self.dimension.lock(); + let player = self.player.lock(); let mut entity = player .entity_mut(&mut dimension_lock) @@ -157,25 +157,17 @@ 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(); - + let player_lock = self.player.lock(); + let mut dimension_lock = self.dimension.lock(); let mut player_entity = player_lock .entity_mut(&mut dimension_lock) .expect("Player must exist"); // server ai step { - let mut physics_state = self.physics_state.lock().unwrap(); + let physics_state = self.physics_state.lock(); player_entity.xxa = physics_state.left_impulse; player_entity.zza = physics_state.forward_impulse; - - // handle jumping_once - if physics_state.jumping_once { - player_entity.jumping = true; - } else if player_entity.jumping { - physics_state.jumping_once = false; - } } player_entity.ai_step(); @@ -183,7 +175,7 @@ impl Client { /// Update the impulse from self.move_direction. The multipler is used for sneaking. pub(crate) fn tick_controls(&mut self, multiplier: Option<f32>) { - let mut physics_state = self.physics_state.lock().unwrap(); + let mut physics_state = self.physics_state.lock(); let mut forward_impulse: f32 = 0.; let mut left_impulse: f32 = 0.; @@ -219,31 +211,29 @@ impl Client { /// Start walking in the given direction. pub fn walk(&mut self, direction: MoveDirection) { - let mut physics_state = self.physics_state.lock().unwrap(); + let mut physics_state = self.physics_state.lock(); physics_state.move_direction = direction; } - /// Jump once next tick. This acts as if you pressed space for one tick in - /// vanilla. If you want to jump continuously, use `set_jumping`. - pub fn jump(&mut self) { - let mut physics_state = self.physics_state.lock().unwrap(); - physics_state.jumping_once = true; - } - /// Toggle whether we're jumping. This acts as if you held space in /// vanilla. If you want to jump once, use the `jump` function. /// /// If you're making a realistic client, calling this function every tick is /// recommended. pub fn set_jumping(&mut self, jumping: bool) { - let player_lock = self.player.lock().unwrap(); - let mut dimension_lock = self.dimension.lock().unwrap(); - let mut player_entity = player_lock - .entity_mut(&mut dimension_lock) - .expect("Player must exist"); + let mut dimension = self.dimension.lock(); + let mut player_entity = self.entity_mut(&mut dimension); player_entity.jumping = jumping; } + + /// Returns whether the player will try to jump next tick. + pub fn jumping(&self) -> bool { + let dimension = self.dimension.lock(); + let player_entity = self.entity(&dimension); + + player_entity.jumping + } } #[derive(Clone, Copy, Debug, Default)] |
