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:
parent
3dc910f079
commit
9e4e417e50
6 changed files with 85 additions and 29 deletions
|
@ -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)]
|
||||||
|
|
57
azalea-client/src/entity_query.rs
Normal file
57
azalea-client/src/entity_query.rs
Normal 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)
|
||||||
|
// }
|
||||||
|
// }
|
|
@ -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};
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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" {
|
||||||
|
|
Loading…
Add table
Reference in a new issue