diff options
| author | mat <git@matdoes.dev> | 2023-10-10 23:21:23 -0500 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2023-10-10 23:21:23 -0500 |
| commit | 9a687f0ffebad80441e036aabe14e7cf80c774d3 (patch) | |
| tree | 2f6ad5a1a14cae23723550c934df395aab1733f6 /azalea/src/pathfinder | |
| parent | 0297b8aacee27d9e86cea781b3751591e32df401 (diff) | |
| download | azalea-drasl-9a687f0ffebad80441e036aabe14e7cf80c774d3.tar.xz | |
start adding mining to pathfinder
Diffstat (limited to 'azalea/src/pathfinder')
| -rw-r--r-- | azalea/src/pathfinder/mining.rs | 30 | ||||
| -rw-r--r-- | azalea/src/pathfinder/mod.rs | 52 | ||||
| -rw-r--r-- | azalea/src/pathfinder/moves/mod.rs | 3 | ||||
| -rw-r--r-- | azalea/src/pathfinder/simulation.rs | 4 |
4 files changed, 76 insertions, 13 deletions
diff --git a/azalea/src/pathfinder/mining.rs b/azalea/src/pathfinder/mining.rs new file mode 100644 index 00000000..d5977973 --- /dev/null +++ b/azalea/src/pathfinder/mining.rs @@ -0,0 +1,30 @@ +use azalea_block::BlockState; +use azalea_inventory::Menu; +use nohash_hasher::IntMap; + +use crate::auto_tool::best_tool_in_hotbar_for_block; + +pub struct MiningCache { + block_state_id_costs: IntMap<u32, f32>, + inventory_menu: Menu, +} + +impl MiningCache { + pub fn new(inventory_menu: Menu) -> Self { + Self { + block_state_id_costs: IntMap::default(), + inventory_menu, + } + } + + pub fn cost_for(&mut self, block: BlockState) -> f32 { + if let Some(cost) = self.block_state_id_costs.get(&block.id) { + *cost + } else { + let best_tool_result = best_tool_in_hotbar_for_block(block, &self.inventory_menu); + let cost = 1. / best_tool_result.percentage_per_tick; + self.block_state_id_costs.insert(block.id, cost); + cost + } + } +} diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs index e92457b8..73ce2967 100644 --- a/azalea/src/pathfinder/mod.rs +++ b/azalea/src/pathfinder/mod.rs @@ -4,6 +4,7 @@ pub mod astar; pub mod costs; pub mod goals; +pub mod mining; pub mod moves; pub mod simulation; pub mod world; @@ -23,6 +24,7 @@ use crate::ecs::{ use crate::pathfinder::moves::PathfinderCtx; use crate::pathfinder::world::CachedWorld; use azalea_client::chat::SendChatEvent; +use azalea_client::inventory::{InventoryComponent, InventorySet}; use azalea_client::movement::walk_listener; use azalea_client::{StartSprintEvent, StartWalkEvent}; use azalea_core::position::{BlockPos, Vec3}; @@ -45,6 +47,7 @@ use std::sync::atomic::{self, AtomicUsize}; use std::sync::Arc; use std::time::{Duration, Instant}; +use self::mining::MiningCache; use self::moves::{ExecuteCtx, IsReachedCtx, SuccessorsFn}; #[derive(Clone, Default)] @@ -82,7 +85,8 @@ impl Plugin for PathfinderPlugin { handle_stop_pathfinding_event, ) .chain() - .before(walk_listener), + .before(walk_listener) + .before(InventorySet), ); } } @@ -116,7 +120,7 @@ pub struct GotoEvent { /// `pathfinder::moves::default_move` pub successors_fn: SuccessorsFn, } -#[derive(Event)] +#[derive(Event, Clone)] pub struct PathFoundEvent { pub entity: Entity, pub start: BlockPos, @@ -175,13 +179,14 @@ fn goto_listener( Option<&ExecutingPath>, &Position, &InstanceName, + &InventoryComponent, )>, instance_container: Res<InstanceContainer>, ) { let thread_pool = AsyncComputeTaskPool::get(); for event in events.iter() { - let (mut pathfinder, executing_path, position, instance_name) = query + let (mut pathfinder, executing_path, position, instance_name, inventory) = query .get_mut(event.entity) .expect("Called goto on an entity that's not in the world"); @@ -217,12 +222,15 @@ fn goto_listener( let goto_id_atomic = pathfinder.goto_id.clone(); let goto_id = goto_id_atomic.fetch_add(1, atomic::Ordering::Relaxed) + 1; + let mining_cache = MiningCache::new(inventory.inventory_menu.clone()); let task = thread_pool.spawn(async move { debug!("start: {start:?}"); let cached_world = CachedWorld::new(world_lock); - let successors = |pos: BlockPos| call_successors_fn(&cached_world, successors_fn, pos); + let successors = |pos: BlockPos| { + call_successors_fn(&cached_world, &mining_cache, successors_fn, pos) + }; let mut attempt_number = 0; @@ -311,12 +319,17 @@ fn handle_tasks( // set the path for the target entity when we get the PathFoundEvent fn path_found_listener( mut events: EventReader<PathFoundEvent>, - mut query: Query<(&mut Pathfinder, Option<&mut ExecutingPath>, &InstanceName)>, + mut query: Query<( + &mut Pathfinder, + Option<&mut ExecutingPath>, + &InstanceName, + &InventoryComponent, + )>, instance_container: Res<InstanceContainer>, mut commands: Commands, ) { for event in events.iter() { - let (mut pathfinder, executing_path, instance_name) = query + let (mut pathfinder, executing_path, instance_name, inventory) = query .get_mut(event.entity) .expect("Path found for an entity that doesn't have a pathfinder"); if let Some(path) = &event.path { @@ -331,8 +344,10 @@ fn path_found_listener( .expect("Entity tried to pathfind but the entity isn't in a valid world"); let successors_fn: moves::SuccessorsFn = event.successors_fn; let cached_world = CachedWorld::new(world_lock); - let successors = - |pos: BlockPos| call_successors_fn(&cached_world, successors_fn, pos); + let mining_cache = MiningCache::new(inventory.inventory_menu.clone()); + let successors = |pos: BlockPos| { + call_successors_fn(&cached_world, &mining_cache, successors_fn, pos) + }; if let Some(first_node_of_new_path) = path.front() { if successors(last_node_of_current_path.target) @@ -503,10 +518,15 @@ fn check_node_reached( } fn check_for_path_obstruction( - mut query: Query<(&Pathfinder, &mut ExecutingPath, &InstanceName)>, + mut query: Query<( + &Pathfinder, + &mut ExecutingPath, + &InstanceName, + &InventoryComponent, + )>, instance_container: Res<InstanceContainer>, ) { - for (pathfinder, mut executing_path, instance_name) in &mut query { + for (pathfinder, mut executing_path, instance_name, inventory) in &mut query { let Some(successors_fn) = pathfinder.successors_fn else { continue; }; @@ -517,7 +537,9 @@ fn check_for_path_obstruction( // obstruction check (the path we're executing isn't possible anymore) let cached_world = CachedWorld::new(world_lock); - let successors = |pos: BlockPos| call_successors_fn(&cached_world, successors_fn, pos); + let mining_cache = MiningCache::new(inventory.inventory_menu.clone()); + let successors = + |pos: BlockPos| call_successors_fn(&cached_world, &mining_cache, successors_fn, pos); if let Some(obstructed_index) = check_path_obstructed( executing_path.last_reached_node, @@ -694,6 +716,11 @@ fn stop_pathfinding_on_instance_change( /// permissions, and it'll make them spam *a lot* of commands. /// /// ``` +/// # use azalea::prelude::*; +/// # use azalea::pathfinder::PathfinderDebugParticles; +/// # #[derive(Component, Clone, Default)] +/// # pub struct State; +/// /// async fn handle(mut bot: Client, event: azalea::Event, state: State) -> anyhow::Result<()> { /// match event { /// azalea::Event::Init => { @@ -704,6 +731,7 @@ fn stop_pathfinding_on_instance_change( /// } /// _ => {} /// } +/// Ok(()) /// } /// ``` #[derive(Component)] @@ -809,6 +837,7 @@ where pub fn call_successors_fn( cached_world: &CachedWorld, + mining_cache: &MiningCache, successors_fn: SuccessorsFn, pos: BlockPos, ) -> Vec<astar::Edge<BlockPos, moves::MoveData>> { @@ -816,6 +845,7 @@ pub fn call_successors_fn( let mut ctx = PathfinderCtx { edges: &mut edges, world: cached_world, + mining_cache, }; successors_fn(&mut ctx, pos); edges diff --git a/azalea/src/pathfinder/moves/mod.rs b/azalea/src/pathfinder/moves/mod.rs index bf1fc5f4..e5b837ea 100644 --- a/azalea/src/pathfinder/moves/mod.rs +++ b/azalea/src/pathfinder/moves/mod.rs @@ -5,7 +5,7 @@ use std::fmt::Debug; use crate::{JumpEvent, LookAtEvent}; -use super::{astar, world::CachedWorld}; +use super::{astar, mining::MiningCache, world::CachedWorld}; use azalea_client::{SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection}; use azalea_core::position::{BlockPos, Vec3}; use bevy_ecs::{entity::Entity, event::EventWriter}; @@ -107,4 +107,5 @@ pub fn default_is_reached( pub struct PathfinderCtx<'a> { pub edges: &'a mut Vec<Edge>, pub world: &'a CachedWorld, + pub mining_cache: &'a MiningCache, } diff --git a/azalea/src/pathfinder/simulation.rs b/azalea/src/pathfinder/simulation.rs index 2b1bfd42..cc077985 100644 --- a/azalea/src/pathfinder/simulation.rs +++ b/azalea/src/pathfinder/simulation.rs @@ -2,7 +2,7 @@ use std::{sync::Arc, time::Duration}; -use azalea_client::PhysicsState; +use azalea_client::{inventory::InventoryComponent, PhysicsState}; use azalea_core::{position::Vec3, resource_location::ResourceLocation}; use azalea_entity::{ attributes::AttributeInstance, metadata::Sprinting, Attributes, EntityDimensions, Physics, @@ -20,6 +20,7 @@ pub struct SimulatedPlayerBundle { pub physics: Physics, pub physics_state: PhysicsState, pub attributes: Attributes, + pub inventory: InventoryComponent, } impl SimulatedPlayerBundle { @@ -37,6 +38,7 @@ impl SimulatedPlayerBundle { speed: AttributeInstance::new(0.1), attack_speed: AttributeInstance::new(4.0), }, + inventory: InventoryComponent::default(), } } } |
