diff --git a/common/src/astar.rs b/common/src/astar.rs index 8bf0104469..3c980e5a63 100644 --- a/common/src/astar.rs +++ b/common/src/astar.rs @@ -34,90 +34,6 @@ impl PartialOrd for PathEntry { } } -fn reconstruct_path(came_from: &HashMap, target: &S) -> Vec -where - S: Clone + Eq + Hash, -{ - let mut path = Vec::new(); - path.push(target.to_owned()); - let mut cur_node = target; - while let Some(node) = came_from.get(cur_node) { - path.push(node.to_owned()); - cur_node = node; - } - path -} - -pub fn astar( - initial: S, - target: S, - mut heuristic: impl FnMut(&S, &S) -> f32, - mut neighbors: impl FnMut(&S) -> I, - mut transition_cost: impl FnMut(&S, &S) -> f32, -) -> Option> -where - S: Clone + Eq + Hash, - I: IntoIterator, -{ - // Set of discovered nodes so far - let mut potential_nodes = BinaryHeap::new(); - potential_nodes.push(PathEntry { - cost: 0.0f32, - node: initial.clone(), - }); - - // For entry e, contains the cheapest node preceding it on the known path from start to e - let mut came_from = HashMap::new(); - - // Contains cheapest cost from 'initial' to the current entry - let mut cheapest_scores = HashMap::new(); - cheapest_scores.insert(initial.clone(), 0.0f32); - - // Contains cheapest score to get to node + heuristic to the end, for an entry - let mut final_scores = HashMap::new(); - final_scores.insert(initial.clone(), heuristic(&initial, &target)); - - // Set of nodes we have already visited - let mut visited = HashSet::new(); - visited.insert(initial.clone()); - - let mut iters = 0; - while let Some(PathEntry { node: current, .. }) = potential_nodes.pop() { - if current == target { - return Some(reconstruct_path(&came_from, ¤t)); - } - - let current_neighbors = neighbors(¤t); - for neighbor in current_neighbors { - let current_cheapest_score = cheapest_scores.get(¤t).unwrap_or(&f32::MAX); - let neighbor_cheapest_score = cheapest_scores.get(&neighbor).unwrap_or(&f32::MAX); - let score = current_cheapest_score + transition_cost(¤t, &neighbor); - if score < *neighbor_cheapest_score { - // Path to the neighbor is better than anything yet recorded - came_from.insert(neighbor.to_owned(), current.to_owned()); - cheapest_scores.insert(neighbor.clone(), score); - let neighbor_score = score + heuristic(&neighbor, &target); - final_scores.insert(neighbor.clone(), neighbor_score); - - if visited.insert(neighbor.clone()) { - potential_nodes.push(PathEntry { - node: neighbor.clone(), - cost: neighbor_score, - }); - } - } - } - - iters += 1; - if iters >= 10000 { - println!("Ran out of turns!"); - break; - } - } - - None -} - pub enum PathResult { None(Path), Exhausted(Path), diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index 3d58f5fa9e..e08dcb3b87 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -94,9 +94,8 @@ impl<'a> System<'a> for Sys { }; } - if let Some(wander_pos) = wander_pos { - if let Some(bearing) = chaser.chase(&*terrain, pos.0, *wander_pos, 2.0) - { + if let Some(wp) = wander_pos { + if let Some(bearing) = chaser.chase(&*terrain, pos.0, *wp, 2.0) { inputs.move_dir = Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero()); inputs.jump.set_state(bearing.z > 1.0); @@ -227,153 +226,6 @@ impl<'a> System<'a> for Sys { } } - /* - const PET_DIST: f32 = 6.0; - const MAX_PET_DIST: f32 = 16.0; - const PATROL_DIST: f32 = 32.0; - const SIGHT_DIST: f32 = 24.0; - const MIN_ATTACK_DIST: f32 = 3.25; - const CHASE_TIME_MIN: f64 = 4.0; - - let mut chase_tgt = None; - let mut choose_target = false; - let mut new_target = None; - - if let Some((target, aggro_time)) = agent.target { - // Chase / attack target - if let (Some(tgt_pos), stats) = (positions.get(target), stats.get(target)) { - if stats.map(|s| s.is_dead).unwrap_or(false) { - // Don't target dead entities - choose_target = true; - } else if pos.0.distance(tgt_pos.0) < SIGHT_DIST - || (time.0 - aggro_time) < CHASE_TIME_MIN - { - chase_tgt = Some((tgt_pos.0, 1.5, true)) - } else { - // Lose sight of enemies - choose_target = true; - } - } else { - choose_target = true; - } - } else { - choose_target = thread_rng().gen::() < 0.05; - } - - // Return to owner - if let Some(owner) = agent.owner { - if let Some(tgt_pos) = positions.get(owner) { - let dist = pos.0.distance(tgt_pos.0); - if dist > MAX_PET_DIST || (dist > PET_DIST && agent.target.is_none()) { - // Follow owner - chase_tgt = Some((tgt_pos.0, 6.0, false)); - } else if agent.target.is_none() { - choose_target = thread_rng().gen::() < 0.02; - } - } else { - agent.owner = None; - } - } else if let Some(patrol_origin) = agent.patrol_origin { - if pos.0.distance(patrol_origin) > PATROL_DIST { - // Return to patrol origin - chase_tgt = Some((patrol_origin, 64.0, false)); - } - } - - // Attack a target that's attacking us - if let Some(stats) = stats.get(entity) { - match stats.health.last_change.1.cause { - comp::HealthSource::Attack { by } => { - if agent.target.is_none() { - new_target = uid_allocator.retrieve_entity_internal(by.id()); - } else if thread_rng().gen::() < 0.005 { - new_target = uid_allocator.retrieve_entity_internal(by.id()); - } - } - _ => {} - } - } - - // Choose a new target - if choose_target { - // Search for new targets - let entities = (&entities, &positions, &stats, alignments.maybe()) - .join() - .filter(|(e, e_pos, e_stats, e_alignment)| { - (e_pos.0 - pos.0).magnitude() < SIGHT_DIST - && *e != entity - && !e_stats.is_dead - && alignment - .and_then(|a| e_alignment.map(|b| a.hostile_towards(*b))) - .unwrap_or(false) - }) - .map(|(e, _, _, _)| e) - .collect::>(); - - new_target = (&entities).choose(&mut thread_rng()).cloned(); - } - - // Update target when attack begins - match agent.target { - Some((tgt, time)) if Some(tgt) == new_target => {}, - _ => agent.target = new_target.map(|tgt| (tgt, time.0)) - } - - // Chase target - if let Some((tgt_pos, min_dist, aggressive)) = chase_tgt { - if let Some(bearing) = agent.chaser.chase(&*terrain, pos.0, tgt_pos, min_dist) { - inputs.move_dir = Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero()); - inputs.jump.set_state(bearing.z > 1.0); - } - - if aggressive && pos.0.distance(tgt_pos) < MIN_ATTACK_DIST { - inputs.look_dir = tgt_pos - pos.0; - inputs.move_dir = Vec2::from(tgt_pos - pos.0) - .try_normalized() - .unwrap_or(Vec2::zero()) - * 0.01; - inputs.primary.set_state(true); - } - - // We're not wandering - agent.wander_pos = None; - } else { - if let Some(wander_pos) = agent.wander_pos { - if pos.0.distance(wander_pos) < 4.0 { - agent.wander_pos = None; - } else { - if let Some(bearing) = agent.chaser.chase(&*terrain, pos.0, wander_pos, 3.0) - { - inputs.move_dir = - Vec2::from(bearing).try_normalized().unwrap_or(Vec2::zero()) * 0.5; - inputs.jump.set_state(bearing.z > 1.0); - } - } - } - - // Choose new wander position - /* - if agent.wander_pos.is_none() || thread_rng().gen::() < 0.005 { - agent.wander_pos = if thread_rng().gen::() < 0.5 { - let max_dist = if agent.owner.is_some() { - PET_DIST - } else { - PATROL_DIST - }; - Some( - agent - .patrol_origin - .unwrap_or(pos.0) - .map(|e| e + (thread_rng().gen::() - 0.5) * max_dist), - ) - } else { - None - }; - } - */ - } - */ - debug_assert!(inputs.move_dir.map(|e| !e.is_nan()).reduce_and()); debug_assert!(inputs.look_dir.map(|e| !e.is_nan()).reduce_and()); } diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 3f6a01d88e..85d42151b1 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -11,7 +11,7 @@ use common::{ npc::{get_npc_name, NpcKind}, state::TimeOfDay, sync::{Uid, WorldSyncExt}, - terrain::{Block, BlockKind, TerrainChunkSize}, + terrain::TerrainChunkSize, vol::RectVolSize, }; use rand::Rng; diff --git a/server/src/sys/waypoint.rs b/server/src/sys/waypoint.rs index 6f2ecbcc26..1dc47d9adb 100644 --- a/server/src/sys/waypoint.rs +++ b/server/src/sys/waypoint.rs @@ -1,5 +1,5 @@ use common::comp::{Player, Pos, Waypoint, WaypointArea}; -use specs::{Entities, Join, Read, ReadStorage, System, Write, WriteStorage}; +use specs::{Entities, Join, ReadStorage, System, WriteStorage}; /// This system will handle loading generated chunks and unloading uneeded chunks. /// 1. Inserts newly generated chunks into the TerrainGrid