#[non_exhaustive]pub struct PathfinderOpts { /* private fields */ }Expand description
Configuration options that the pathfinder will use when calculating and executing a path.
This can be passed into Client::goto_with_opts or
Client::start_goto_with_opts.
// example config to disallow mining blocks and to not do parkour
let opts = PathfinderOpts::new()
.allow_mining(false)
.successors_fn(moves::basic::basic_move);Implementations§
Source§impl PathfinderOpts
impl PathfinderOpts
Sourcepub const fn new() -> Self
pub const fn new() -> Self
Examples found in repository?
132async fn handle(bot: Client, event: azalea::Event, state: State) -> eyre::Result<()> {
133 let swarm = bot.resource::<SwarmState>();
134
135 match event {
136 azalea::Event::Init => {
137 bot.set_client_information(ClientInformation {
138 view_distance: 32,
139 ..Default::default()
140 })?;
141 if swarm.args.pathfinder_debug_particles {
142 bot.ecs
143 .write()
144 .entity_mut(bot.entity)
145 .insert(PathfinderDebugParticles);
146 }
147 }
148 azalea::Event::Chat(chat) => {
149 let (Some(username), content) = chat.split_sender_and_content() else {
150 return Ok(());
151 };
152 if username != swarm.args.owner_username {
153 return Ok(());
154 }
155
156 println!("{:?}", chat.message());
157
158 let command = if chat.is_whisper() {
159 Some(content)
160 } else {
161 content.strip_prefix('!').map(|s| s.to_owned())
162 };
163 if let Some(command) = command {
164 match swarm.commands.execute(
165 command,
166 Mutex::new(CommandSource {
167 bot: bot.clone(),
168 chat: chat.clone(),
169 state: state.clone(),
170 }),
171 ) {
172 Ok(Ok(_)) => {}
173 Ok(Err(err)) => {
174 eprintln!("azalea error: {err:?}");
175 let command_source = CommandSource {
176 bot,
177 chat: chat.clone(),
178 state: state.clone(),
179 };
180 command_source.reply(format!("azalea error: {err:?}"));
181 }
182 Err(err) => {
183 eprintln!("{err:?}");
184 let command_source = CommandSource {
185 bot,
186 chat: chat.clone(),
187 state: state.clone(),
188 };
189 command_source.reply(format!("{err:?}"));
190 }
191 }
192 }
193 }
194 azalea::Event::Tick => {
195 killaura::tick(bot.clone(), state.clone())?;
196
197 if bot.ticks_connected().is_multiple_of(5) {
198 if let Some(following) = &*state.following_entity.lock()
199 && following.is_alive()
200 {
201 let goal = RadiusGoal::new(following.position()?, 3.);
202 if bot.is_calculating_path() {
203 // keep waiting
204 } else if !goal.success(bot.position()?.into()) || bot.is_executing_path() {
205 bot.start_goto_with_opts(
206 goal,
207 PathfinderOpts::new()
208 .retry_on_no_path(false)
209 .max_timeout(Duration::from_secs(1)),
210 );
211 } else {
212 following.look_at()?;
213 }
214 }
215 }
216 }
217 azalea::Event::Login => {
218 println!("Got login event")
219 }
220 _ => {}
221 }
222
223 Ok(())
224}Sourcepub fn successors_fn(self, successors_fn: SuccessorsFn) -> Self
pub fn successors_fn(self, successors_fn: SuccessorsFn) -> Self
Set the function that’s used for checking what moves are possible.
Defaults to moves::default_move.
Sourcepub fn allow_mining(self, allow_mining: bool) -> Self
pub fn allow_mining(self, allow_mining: bool) -> Self
Set whether the bot is allowed to break blocks while pathfinding.
Defaults to true.
Sourcepub fn retry_on_no_path(self, retry_on_no_path: bool) -> Self
pub fn retry_on_no_path(self, retry_on_no_path: bool) -> Self
Whether we should recalculate the path when the pathfinder timed out and there’s no partial path to try.
Defaults to true.
Examples found in repository?
132async fn handle(bot: Client, event: azalea::Event, state: State) -> eyre::Result<()> {
133 let swarm = bot.resource::<SwarmState>();
134
135 match event {
136 azalea::Event::Init => {
137 bot.set_client_information(ClientInformation {
138 view_distance: 32,
139 ..Default::default()
140 })?;
141 if swarm.args.pathfinder_debug_particles {
142 bot.ecs
143 .write()
144 .entity_mut(bot.entity)
145 .insert(PathfinderDebugParticles);
146 }
147 }
148 azalea::Event::Chat(chat) => {
149 let (Some(username), content) = chat.split_sender_and_content() else {
150 return Ok(());
151 };
152 if username != swarm.args.owner_username {
153 return Ok(());
154 }
155
156 println!("{:?}", chat.message());
157
158 let command = if chat.is_whisper() {
159 Some(content)
160 } else {
161 content.strip_prefix('!').map(|s| s.to_owned())
162 };
163 if let Some(command) = command {
164 match swarm.commands.execute(
165 command,
166 Mutex::new(CommandSource {
167 bot: bot.clone(),
168 chat: chat.clone(),
169 state: state.clone(),
170 }),
171 ) {
172 Ok(Ok(_)) => {}
173 Ok(Err(err)) => {
174 eprintln!("azalea error: {err:?}");
175 let command_source = CommandSource {
176 bot,
177 chat: chat.clone(),
178 state: state.clone(),
179 };
180 command_source.reply(format!("azalea error: {err:?}"));
181 }
182 Err(err) => {
183 eprintln!("{err:?}");
184 let command_source = CommandSource {
185 bot,
186 chat: chat.clone(),
187 state: state.clone(),
188 };
189 command_source.reply(format!("{err:?}"));
190 }
191 }
192 }
193 }
194 azalea::Event::Tick => {
195 killaura::tick(bot.clone(), state.clone())?;
196
197 if bot.ticks_connected().is_multiple_of(5) {
198 if let Some(following) = &*state.following_entity.lock()
199 && following.is_alive()
200 {
201 let goal = RadiusGoal::new(following.position()?, 3.);
202 if bot.is_calculating_path() {
203 // keep waiting
204 } else if !goal.success(bot.position()?.into()) || bot.is_executing_path() {
205 bot.start_goto_with_opts(
206 goal,
207 PathfinderOpts::new()
208 .retry_on_no_path(false)
209 .max_timeout(Duration::from_secs(1)),
210 );
211 } else {
212 following.look_at()?;
213 }
214 }
215 }
216 }
217 azalea::Event::Login => {
218 println!("Got login event")
219 }
220 _ => {}
221 }
222
223 Ok(())
224}Sourcepub fn min_timeout(self, min_timeout: impl Into<PathfinderTimeout>) -> Self
pub fn min_timeout(self, min_timeout: impl Into<PathfinderTimeout>) -> Self
The minimum amount of time that should pass before the A* pathfinder
function can return a timeout if it finds a path that seems good enough.
It may take up to Self::max_timeout if it can’t immediately find
a usable path.
Defaults to PathfinderTimeout::Time(Duration::from_secs(1)).
Also see PathfinderTimeout::Nodes
Sourcepub fn max_timeout(self, max_timeout: impl Into<PathfinderTimeout>) -> Self
pub fn max_timeout(self, max_timeout: impl Into<PathfinderTimeout>) -> Self
The absolute maximum amount of time that the pathfinder function can take to find a path.
If it takes this long, it means no usable path was found (so it might be impossible).
Defaults to PathfinderTimeout::Time(Duration::from_secs(5)).
Examples found in repository?
132async fn handle(bot: Client, event: azalea::Event, state: State) -> eyre::Result<()> {
133 let swarm = bot.resource::<SwarmState>();
134
135 match event {
136 azalea::Event::Init => {
137 bot.set_client_information(ClientInformation {
138 view_distance: 32,
139 ..Default::default()
140 })?;
141 if swarm.args.pathfinder_debug_particles {
142 bot.ecs
143 .write()
144 .entity_mut(bot.entity)
145 .insert(PathfinderDebugParticles);
146 }
147 }
148 azalea::Event::Chat(chat) => {
149 let (Some(username), content) = chat.split_sender_and_content() else {
150 return Ok(());
151 };
152 if username != swarm.args.owner_username {
153 return Ok(());
154 }
155
156 println!("{:?}", chat.message());
157
158 let command = if chat.is_whisper() {
159 Some(content)
160 } else {
161 content.strip_prefix('!').map(|s| s.to_owned())
162 };
163 if let Some(command) = command {
164 match swarm.commands.execute(
165 command,
166 Mutex::new(CommandSource {
167 bot: bot.clone(),
168 chat: chat.clone(),
169 state: state.clone(),
170 }),
171 ) {
172 Ok(Ok(_)) => {}
173 Ok(Err(err)) => {
174 eprintln!("azalea error: {err:?}");
175 let command_source = CommandSource {
176 bot,
177 chat: chat.clone(),
178 state: state.clone(),
179 };
180 command_source.reply(format!("azalea error: {err:?}"));
181 }
182 Err(err) => {
183 eprintln!("{err:?}");
184 let command_source = CommandSource {
185 bot,
186 chat: chat.clone(),
187 state: state.clone(),
188 };
189 command_source.reply(format!("{err:?}"));
190 }
191 }
192 }
193 }
194 azalea::Event::Tick => {
195 killaura::tick(bot.clone(), state.clone())?;
196
197 if bot.ticks_connected().is_multiple_of(5) {
198 if let Some(following) = &*state.following_entity.lock()
199 && following.is_alive()
200 {
201 let goal = RadiusGoal::new(following.position()?, 3.);
202 if bot.is_calculating_path() {
203 // keep waiting
204 } else if !goal.success(bot.position()?.into()) || bot.is_executing_path() {
205 bot.start_goto_with_opts(
206 goal,
207 PathfinderOpts::new()
208 .retry_on_no_path(false)
209 .max_timeout(Duration::from_secs(1)),
210 );
211 } else {
212 following.look_at()?;
213 }
214 }
215 }
216 }
217 azalea::Event::Login => {
218 println!("Got login event")
219 }
220 _ => {}
221 }
222
223 Ok(())
224}Trait Implementations§
Source§impl Clone for PathfinderOpts
impl Clone for PathfinderOpts
Source§fn clone(&self) -> PathfinderOpts
fn clone(&self) -> PathfinderOpts
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for PathfinderOpts
impl Debug for PathfinderOpts
Auto Trait Implementations§
impl Freeze for PathfinderOpts
impl RefUnwindSafe for PathfinderOpts
impl Send for PathfinderOpts
impl Sync for PathfinderOpts
impl Unpin for PathfinderOpts
impl UnsafeUnpin for PathfinderOpts
impl UnwindSafe for PathfinderOpts
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> CompatExt for T
impl<T> CompatExt for T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self using default().
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more