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

try to add a .entity_by function

still doesn't work because i want to make the predicate magic
This commit is contained in:
mat 2023-01-16 22:58:20 -06:00
parent 3dc910f079
commit 9e4e417e50
6 changed files with 85 additions and 29 deletions

View file

@ -37,13 +37,14 @@ use azalea_world::{
}; };
use bevy_app::App; use bevy_app::App;
use bevy_ecs::{ use bevy_ecs::{
query::WorldQuery, query::{ReadOnlyWorldQuery, WorldQuery},
schedule::{IntoSystemDescriptor, Schedule, Stage, SystemSet}, schedule::{IntoSystemDescriptor, Schedule, Stage, SystemSet},
world::EntityRef,
}; };
use bevy_time::TimePlugin; use bevy_time::TimePlugin;
use iyes_loopless::prelude::*; use iyes_loopless::prelude::*;
use log::{debug, error}; use log::{debug, error};
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, MutexGuard, RwLock};
use std::{fmt::Debug, io, net::SocketAddr, ops::DerefMut, sync::Arc, time::Duration}; use std::{fmt::Debug, io, net::SocketAddr, ops::DerefMut, sync::Arc, time::Duration};
use thiserror::Error; use thiserror::Error;
use tokio::{sync::mpsc, time}; use tokio::{sync::mpsc, time};
@ -476,16 +477,6 @@ impl Client {
Ok(()) Ok(())
} }
/// A convenience function for getting components of our player's entity.
pub fn query<'w, Q: WorldQuery>(
&self,
ecs: &'w mut bevy_ecs::world::World,
) -> <Q as WorldQuery>::Item<'w> {
ecs.query::<Q>()
.get_mut(ecs, self.entity)
.expect("Our client is missing a required component.")
}
} }
#[doc(hidden)] #[doc(hidden)]

View file

@ -0,0 +1,57 @@
use azalea_world::entity::Entity;
use bevy_ecs::query::{ReadOnlyWorldQuery, WorldQuery};
use crate::Client;
impl Client {
/// A convenience function for getting components of our player's entity.
pub fn query<'w, Q: WorldQuery>(
&self,
ecs: &'w mut bevy_ecs::world::World,
) -> <Q as WorldQuery>::Item<'w> {
ecs.query::<Q>()
.get_mut(ecs, self.entity)
.expect("Our client is missing a required component.")
}
/// Return a lightweight [`Entity`] for the entity that matches the given
/// predicate function.
///
/// You can then use [`Self::map_entity`] to get components from this
/// entity.
pub fn entity_by<'a, F: ReadOnlyWorldQuery, Q: ReadOnlyWorldQuery>(
&mut self,
mut predicate: impl EntityPredicate<'a, Q>,
) -> Option<Entity> {
let mut ecs = self.ecs.lock();
let mut query = ecs.query_filtered::<(Entity, Q), F>();
let entity = query
.iter_mut(&mut ecs)
.find(|(_, q)| predicate.matches(q))
.map(|(entity, _)| entity);
entity
}
}
pub trait EntityPredicate<'a, Q: ReadOnlyWorldQuery> {
fn matches(&self, components: &<Q as WorldQuery>::Item<'a>) -> bool;
}
impl<'a, F, Q> EntityPredicate<'a, Q> for F
where
F: Fn(Q) -> bool,
Q: ReadOnlyWorldQuery,
{
fn matches(&self, query: &<Q as WorldQuery>::Item<'a>) -> bool {
(self)(query)
}
}
// impl<'a, F, Q1, Q2> EntityPredicate<'a, (Q1, Q2)> for F
// where
// F: Fn(Q1, Q2) -> bool,
// Q1: WorldQuery<Item<'a> = Q1>,
// Q2: WorldQuery<Item<'a> = Q2>,
// {
// fn matches(&self, query: <(Q1, Q2) as WorldQuery>::Item<'_>) -> bool {
// (self)(query.0, query.1)
// }
// }

View file

@ -13,6 +13,7 @@
mod account; mod account;
mod chat; mod chat;
mod client; mod client;
mod entity_query;
mod get_mc_dir; mod get_mc_dir;
mod local_player; mod local_player;
mod movement; mod movement;
@ -22,6 +23,7 @@ mod player;
mod plugins; mod plugins;
pub use account::Account; pub use account::Account;
pub use bevy_ecs as ecs;
pub use client::{start_ecs, ChatPacket, Client, ClientInformation, Event, JoinError}; pub use client::{start_ecs, ChatPacket, Client, ClientInformation, Event, JoinError};
pub use local_player::LocalPlayer; pub use local_player::LocalPlayer;
pub use movement::{SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection}; pub use movement::{SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection};

View file

@ -46,12 +46,16 @@ async fn swarm_handle(
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
match event { match event {
SwarmEvent::Tick => { SwarmEvent::Tick => {
// choose an arbitrary player within render distance to target if let Some(target_entity) =
if let Some(target) = swarm.worlds.read().entity_by(|_: &Player| true) { swarm.entity_by::<Player>(|name: &Name| name == "Herobrine")
{
let target_bounding_box =
swarm.map_entity(target_entity, |bb: &BoundingBox| bb.clone());
for (bot, bot_state) in swarm { for (bot, bot_state) in swarm {
bot.tick_goto_goal(pathfinder::Goals::Reach(target.bounding_box)); bot.tick_goto_goal(pathfinder::Goals::Reach(target_bounding_box));
// if target.bounding_box.distance(bot.eyes) < bot.reach_distance() { // if target.bounding_box.distance(bot.eyes) < bot.reach_distance() {
if azalea::entities::can_reach(bot.entity(), target.bounding_box) { if azalea::entities::can_reach(bot.entity(), target_bounding_box) {
bot.swing(); bot.swing();
} }
if !bot.using_held_item() && bot.hunger() <= 17 { if !bot.using_held_item() && bot.hunger() <= 17 {

View file

@ -16,7 +16,7 @@ use log::error;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use std::{future::Future, net::SocketAddr, sync::Arc, time::Duration}; use std::{future::Future, net::SocketAddr, sync::Arc, time::Duration};
use thiserror::Error; use thiserror::Error;
use tokio::sync::mpsc::{self, UnboundedSender}; use tokio::sync::mpsc;
/// A helper macro that generates a [`SwarmPlugins`] struct from a list of /// A helper macro that generates a [`SwarmPlugins`] struct from a list of
/// objects that implement [`SwarmPlugin`]. /// objects that implement [`SwarmPlugin`].
@ -57,10 +57,10 @@ pub struct Swarm<S> {
/// Plugins that are set for new bots /// Plugins that are set for new bots
plugins: Plugins, plugins: Plugins,
bots_tx: UnboundedSender<(Option<Event>, (Client, S))>, bots_tx: mpsc::UnboundedSender<(Option<Event>, (Client, S))>,
swarm_tx: UnboundedSender<SwarmEvent>, swarm_tx: mpsc::UnboundedSender<SwarmEvent>,
run_schedule_sender: UnboundedSender<()>, run_schedule_sender: mpsc::Sender<()>,
} }
/// An event about something that doesn't have to do with a single bot. /// An event about something that doesn't have to do with a single bot.
@ -239,7 +239,7 @@ pub async fn start_swarm<
let (bots_tx, mut bots_rx) = mpsc::unbounded_channel(); let (bots_tx, mut bots_rx) = mpsc::unbounded_channel();
let (swarm_tx, mut swarm_rx) = mpsc::unbounded_channel(); let (swarm_tx, mut swarm_rx) = mpsc::unbounded_channel();
let (run_schedule_sender, run_schedule_receiver) = mpsc::unbounded_channel(); let (run_schedule_sender, run_schedule_receiver) = mpsc::channel(1);
let ecs_lock = start_ecs(run_schedule_receiver, run_schedule_sender.clone()); let ecs_lock = start_ecs(run_schedule_receiver, run_schedule_sender.clone());
let mut swarm = Swarm { let mut swarm = Swarm {

View file

@ -1,3 +1,4 @@
use azalea::ecs::query::With;
use azalea::entity::metadata::Player; use azalea::entity::metadata::Player;
use azalea::pathfinder::BlockPosGoal; use azalea::pathfinder::BlockPosGoal;
// use azalea::ClientInformation; // use azalea::ClientInformation;
@ -92,13 +93,14 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
return Ok(()) return Ok(())
}; };
let mut ecs = bot.ecs.lock(); let mut ecs = bot.ecs.lock();
let entity = bot // let entity = bot
.ecs // .ecs
.lock() // .lock()
.query::<&Player>() // .query::<&Player>()
.iter(&mut ecs) // .iter(&mut ecs)
.find(|e| e.name() == Some(sender)); // .find(|e| e.name() == Some(sender));
// let entity = None; // let entity = bot.entity_by::<With<Player>>(|name: &Name| name == sender);
let entity = bot.entity_by(|name: &Name| name == sender);
if let Some(entity) = entity { if let Some(entity) = entity {
if m.content() == "goto" { if m.content() == "goto" {
let target_pos_vec3 = entity.pos(); let target_pos_vec3 = entity.pos();
@ -108,7 +110,7 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
let target_pos_vec3 = entity.pos(); let target_pos_vec3 = entity.pos();
let target_pos: BlockPos = target_pos_vec3.into(); let target_pos: BlockPos = target_pos_vec3.into();
println!("target_pos: {:?}", target_pos); println!("target_pos: {:?}", target_pos);
bot.look_at(&target_pos.center()); bot.look_at(target_pos.center());
} else if m.content() == "jump" { } else if m.content() == "jump" {
bot.set_jumping(true); bot.set_jumping(true);
} else if m.content() == "walk" { } else if m.content() == "walk" {