From 8ea3d728c10962b25d9db4fb35e93ad9bd1ba907 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 20 Jan 2023 19:01:52 +0000 Subject: [PATCH] everything compiles --- azalea-auth/src/game_profile.rs | 2 ++ azalea-client/src/chat.rs | 2 +- azalea-client/src/client.rs | 4 +-- azalea-client/src/entity_query.rs | 22 ++++++++++++ azalea-client/src/lib.rs | 2 +- azalea-client/src/local_player.rs | 14 +++++--- azalea-client/src/packet_handling.rs | 12 ++++--- bot/src/main.rs | 53 ++++++++++++++++------------ 8 files changed, 76 insertions(+), 35 deletions(-) diff --git a/azalea-auth/src/game_profile.rs b/azalea-auth/src/game_profile.rs index 39cd29e7..1996e29e 100755 --- a/azalea-auth/src/game_profile.rs +++ b/azalea-auth/src/game_profile.rs @@ -4,7 +4,9 @@ use uuid::Uuid; #[derive(McBuf, Debug, Clone, Default)] pub struct GameProfile { + /// The UUID of the player. pub uuid: Uuid, + /// The username of the player. pub name: String, pub properties: HashMap, } diff --git a/azalea-client/src/chat.rs b/azalea-client/src/chat.rs index 3a7ac1ad..f1b62c77 100755 --- a/azalea-client/src/chat.rs +++ b/azalea-client/src/chat.rs @@ -153,7 +153,7 @@ impl Client { /// # Ok(()) /// # } /// ``` - pub async fn chat(&self, message: &str) { + pub fn chat(&self, message: &str) { if let Some(command) = message.strip_prefix('/') { self.send_command_packet(command); } else { diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 638eac5e..ccd222de 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -1,7 +1,7 @@ pub use crate::chat::ChatPacket; use crate::{ local_player::{ - death_event, send_tick_event, update_in_loaded_chunk, LocalPlayer, PhysicsState, + death_event, send_tick_event, update_in_loaded_chunk, LocalPlayer, PhysicsState, GameProfileComponent, }, movement::{local_player_ai_step, send_position, sprint_listener, walk_listener}, packet_handling::{self, PacketHandlerPlugin}, @@ -232,7 +232,6 @@ impl Client { let mut local_player = crate::local_player::LocalPlayer::new( entity, - game_profile, packet_writer_sender, // default to an empty world, it'll be set correctly later when we // get the login packet @@ -258,6 +257,7 @@ impl Client { ecs.entity_mut(entity).insert(( local_player, packet_receiver, + GameProfileComponent(game_profile), PhysicsState::default(), Local, )); diff --git a/azalea-client/src/entity_query.rs b/azalea-client/src/entity_query.rs index 32608d1b..ca962fc0 100644 --- a/azalea-client/src/entity_query.rs +++ b/azalea-client/src/entity_query.rs @@ -25,12 +25,34 @@ impl Client { /// /// You can then use [`Self::map_entity`] to get components from this /// entity. + /// + /// # Example + /// Note that this will very likely change in the future. + /// ``` + /// let entity = bot.entity_by::, (&GameProfileComponent,)>( + /// |profile: &&GameProfileComponent| profile.name == sender, + /// ); + /// if let Some(entity) = entity { + /// let position = bot.entity_components::(entity); + /// } + /// ``` pub fn entity_by( &mut self, predicate: impl EntityPredicate, ) -> Option { predicate.find(self.ecs.clone()) } + + /// Get a component from an entity. Note that this will return an owned type + /// (i.e. not a reference) so it may be expensive for larger types. + pub fn entity_components(&mut self, entity: Entity) -> Q { + let mut ecs = self.ecs.lock(); + let mut q = ecs.query::<&Q>(); + let components = q + .get(&ecs, entity) + .expect("Entity components must be present in Client::entity)components."); + components.clone() + } } pub trait EntityPredicate { diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs index e51be11d..bbef5e22 100644 --- a/azalea-client/src/lib.rs +++ b/azalea-client/src/lib.rs @@ -26,7 +26,7 @@ mod plugins; pub use account::Account; pub use bevy_ecs as ecs; pub use client::{start_ecs, ChatPacket, Client, ClientInformation, Event, JoinError}; -pub use local_player::LocalPlayer; +pub use local_player::{GameProfileComponent, LocalPlayer}; pub use movement::{SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection}; pub use player::PlayerInfo; pub use plugins::{Plugin, PluginState, PluginStates, Plugins}; diff --git a/azalea-client/src/local_player.rs b/azalea-client/src/local_player.rs index 373ee74a..4f545a59 100644 --- a/azalea-client/src/local_player.rs +++ b/azalea-client/src/local_player.rs @@ -8,6 +8,7 @@ use azalea_world::{ EntityInfos, PartialWorld, World, }; use bevy_ecs::{component::Component, query::Added, system::Query}; +use derive_more::{Deref, DerefMut}; use log::warn; use parking_lot::RwLock; use thiserror::Error; @@ -19,8 +20,6 @@ use crate::{ClientInformation, Event, PlayerInfo, WalkDirection}; /// A player that you control that is currently in a Minecraft server. #[derive(Component)] pub struct LocalPlayer { - pub profile: GameProfile, - pub packet_writer: mpsc::UnboundedSender, pub client_information: ClientInformation, @@ -59,6 +58,14 @@ pub struct PhysicsState { pub left_impulse: f32, } +/// A component only present in players that contains the [`GameProfile`] (which +/// you can use to get a player's name). +/// +/// Note that it's possible for this to be missing in a player if the server +/// never sent the player info for them (though this is uncommon). +#[derive(Component, Clone, Debug, Deref, DerefMut)] +pub struct GameProfileComponent(pub GameProfile); + /// Marks a [`LocalPlayer`] that's in a loaded chunk. This is updated at the /// beginning of every tick. #[derive(Component)] @@ -71,7 +78,6 @@ impl LocalPlayer { /// defaults, otherwise use [`Client::join`]. pub fn new( entity: Entity, - profile: GameProfile, packet_writer: mpsc::UnboundedSender, world: Arc>, tx: mpsc::UnboundedSender, @@ -79,8 +85,6 @@ impl LocalPlayer { let client_information = ClientInformation::default(); LocalPlayer { - profile, - packet_writer, client_information: ClientInformation::default(), diff --git a/azalea-client/src/packet_handling.rs b/azalea-client/src/packet_handling.rs index 5681cfa6..0b74d291 100644 --- a/azalea-client/src/packet_handling.rs +++ b/azalea-client/src/packet_handling.rs @@ -31,7 +31,10 @@ use log::{debug, error, trace, warn}; use parking_lot::Mutex; use tokio::sync::mpsc; -use crate::{local_player::LocalPlayer, ChatPacket, ClientInformation, Event, PlayerInfo}; +use crate::{ + local_player::{GameProfileComponent, LocalPlayer}, + ChatPacket, ClientInformation, Event, PlayerInfo, +}; pub struct PacketHandlerPlugin; @@ -89,13 +92,13 @@ fn handle_packets(ecs: &mut bevy_ecs::world::World) { let mut system_state: SystemState<( Commands, - Query<&mut LocalPlayer>, + Query<(&mut LocalPlayer, &GameProfileComponent)>, ResMut, ResMut, )> = SystemState::new(ecs); let (mut commands, mut query, mut world_container, mut entity_infos) = system_state.get_mut(ecs); - let mut local_player = query.get_mut(player_entity).unwrap(); + let (mut local_player, game_profile) = query.get_mut(player_entity).unwrap(); { // TODO: have registry_holder be a struct because this sucks rn @@ -172,7 +175,7 @@ fn handle_packets(ecs: &mut bevy_ecs::world::World) { let player_bundle = PlayerBundle { entity: EntityBundle::new( - local_player.profile.uuid, + game_profile.uuid, Vec3::default(), azalea_registry::EntityKind::Player, world_name, @@ -527,6 +530,7 @@ fn handle_packets(ecs: &mut bevy_ecs::world::World) { LoadedBy(HashSet::from([player_entity])), bundle, )); + println!("spawned player entity: {:?}", spawned.id()); } else { warn!("got add player packet but we haven't gotten a login packet yet"); diff --git a/bot/src/main.rs b/bot/src/main.rs index 700253cf..daa7d8cd 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -5,7 +5,7 @@ use azalea::entity::metadata::Player; use azalea::entity::Position; use azalea::pathfinder::BlockPosGoal; // use azalea::ClientInformation; -use azalea::{prelude::*, BlockPos, Swarm, SwarmEvent, WalkDirection}; +use azalea::{prelude::*, BlockPos, GameProfileComponent, Swarm, SwarmEvent, WalkDirection}; use azalea::{Account, Client, Event}; use azalea_protocol::packets::game::serverbound_client_command_packet::ServerboundClientCommandPacket; use std::time::Duration; @@ -103,28 +103,37 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result< // .iter(&mut ecs) // .find(|e| e.name() == Some(sender)); // let entity = bot.entity_by::>(|name: &Name| name == sender); - // let entity = bot.entity_by(|name: &Name| name == sender); - let entity = bot.entity_by::, (&Position,)>(|pos: &&Position| true); + let entity = bot.entity_by::, (&GameProfileComponent,)>( + |profile: &&GameProfileComponent| profile.name == sender, + ); if let Some(entity) = entity { - // if m.content() == "goto" { - // let target_pos_vec3 = entity.pos(); - // let target_pos: BlockPos = target_pos_vec3.into(); - // bot.goto(BlockPosGoal::from(target_pos)); - // } else if m.content() == "look" { - // let target_pos_vec3 = entity.pos(); - // let target_pos: BlockPos = target_pos_vec3.into(); - // println!("target_pos: {:?}", target_pos); - // bot.look_at(target_pos.center()); - // } else if m.content() == "jump" { - // bot.set_jumping(true); - // } else if m.content() == "walk" { - // bot.walk(WalkDirection::Forward); - // } else if m.content() == "stop" { - // bot.set_jumping(false); - // bot.walk(WalkDirection::None); - // } else if m.content() == "lag" { - // std::thread::sleep(Duration::from_millis(1000)); - // } + match m.content().as_str() { + "goto" => { + let entity_pos = bot.entity_components::(entity); + let target_pos: BlockPos = entity_pos.into(); + bot.goto(BlockPosGoal::from(target_pos)); + } + "look" => { + let entity_pos = bot.entity_components::(entity); + let target_pos: BlockPos = entity_pos.into(); + println!("target_pos: {:?}", target_pos); + bot.look_at(target_pos.center()); + } + "jump" => { + bot.set_jumping(true); + } + "walk" => { + bot.walk(WalkDirection::Forward); + } + "stop" => { + bot.set_jumping(false); + bot.walk(WalkDirection::None); + } + "lag" => { + std::thread::sleep(Duration::from_millis(1000)); + } + _ => {} + } } } Event::Death(_) => {