mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 23:44:38 +00:00
descend up to 3 blocks in pathfinder
This commit is contained in:
parent
a839c6a923
commit
509c154b4d
2 changed files with 102 additions and 74 deletions
|
@ -157,10 +157,13 @@ fn goto_listener(
|
||||||
|
|
||||||
let world = world_lock.read();
|
let world = world_lock.read();
|
||||||
for possible_move in &possible_moves {
|
for possible_move in &possible_moves {
|
||||||
edges.push(Edge {
|
let possible_move = possible_move.get(&world, node);
|
||||||
target: possible_move.next_node(node),
|
if let Some(possible_move) = possible_move {
|
||||||
cost: possible_move.cost(&world, node),
|
edges.push(Edge {
|
||||||
});
|
target: possible_move.node,
|
||||||
|
cost: possible_move.cost,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
edges
|
edges
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,89 +34,116 @@ fn is_standable(pos: &BlockPos, world: &Instance) -> bool {
|
||||||
is_block_solid(&pos.down(1), world) && is_passable(pos, world)
|
is_block_solid(&pos.down(1), world) && is_passable(pos, world)
|
||||||
}
|
}
|
||||||
|
|
||||||
const JUMP_COST: f32 = 0.5;
|
/// Get the amount of air blocks until the next solid block below this one.
|
||||||
const WALK_ONE_BLOCK_COST: f32 = 1.0;
|
fn fall_distance(pos: &BlockPos, world: &Instance) -> u32 {
|
||||||
|
let mut distance = 0;
|
||||||
|
let mut current_pos = pos.down(1);
|
||||||
|
while is_block_passable(¤t_pos, world) {
|
||||||
|
distance += 1;
|
||||||
|
current_pos = current_pos.down(1);
|
||||||
|
|
||||||
pub trait Move: Send + Sync {
|
if current_pos.y < world.chunks.min_y {
|
||||||
fn cost(&self, world: &Instance, node: &Node) -> f32;
|
return u32::MAX;
|
||||||
/// Returns by how much the entity's position should be changed when this
|
|
||||||
/// move is executed.
|
|
||||||
fn offset(&self) -> BlockPos;
|
|
||||||
fn next_node(&self, node: &Node) -> Node {
|
|
||||||
Node {
|
|
||||||
pos: node.pos + self.offset(),
|
|
||||||
vertical_vel: VerticalVel::None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
distance
|
||||||
|
}
|
||||||
|
|
||||||
|
const JUMP_COST: f32 = 0.5;
|
||||||
|
const WALK_ONE_BLOCK_COST: f32 = 1.0;
|
||||||
|
const FALL_ONE_BLOCK_COST: f32 = 0.5;
|
||||||
|
|
||||||
|
pub trait Move: Send + Sync {
|
||||||
|
fn get(&self, world: &Instance, node: &Node) -> Option<MoveResult>;
|
||||||
|
}
|
||||||
|
pub struct MoveResult {
|
||||||
|
pub node: Node,
|
||||||
|
pub cost: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ForwardMove(pub CardinalDirection);
|
pub struct ForwardMove(pub CardinalDirection);
|
||||||
impl Move for ForwardMove {
|
impl Move for ForwardMove {
|
||||||
fn cost(&self, world: &Instance, node: &Node) -> f32 {
|
fn get(&self, world: &Instance, node: &Node) -> Option<MoveResult> {
|
||||||
if is_standable(&(node.pos + self.offset()), world)
|
let offset = BlockPos::new(self.0.x(), 0, self.0.z());
|
||||||
&& node.vertical_vel == VerticalVel::None
|
|
||||||
{
|
if !is_standable(&(node.pos + offset), world) || node.vertical_vel != VerticalVel::None {
|
||||||
WALK_ONE_BLOCK_COST
|
return None;
|
||||||
} else {
|
|
||||||
f32::INFINITY
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
fn offset(&self) -> BlockPos {
|
let cost = WALK_ONE_BLOCK_COST;
|
||||||
BlockPos::new(self.0.x(), 0, self.0.z())
|
|
||||||
|
Some(MoveResult {
|
||||||
|
node: Node {
|
||||||
|
pos: node.pos + offset,
|
||||||
|
vertical_vel: VerticalVel::None,
|
||||||
|
},
|
||||||
|
cost,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AscendMove(pub CardinalDirection);
|
pub struct AscendMove(pub CardinalDirection);
|
||||||
impl Move for AscendMove {
|
impl Move for AscendMove {
|
||||||
fn cost(&self, world: &Instance, node: &Node) -> f32 {
|
fn get(&self, world: &Instance, node: &Node) -> Option<MoveResult> {
|
||||||
if node.vertical_vel == VerticalVel::None
|
let offset = BlockPos::new(self.0.x(), 1, self.0.z());
|
||||||
&& is_block_passable(&node.pos.up(2), world)
|
|
||||||
&& is_standable(&(node.pos + self.offset()), world)
|
if node.vertical_vel != VerticalVel::None
|
||||||
|
|| !is_block_passable(&node.pos.up(2), world)
|
||||||
|
|| !is_standable(&(node.pos + offset), world)
|
||||||
{
|
{
|
||||||
WALK_ONE_BLOCK_COST + JUMP_COST
|
return None;
|
||||||
} else {
|
|
||||||
f32::INFINITY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn offset(&self) -> BlockPos {
|
|
||||||
BlockPos::new(self.0.x(), 1, self.0.z())
|
|
||||||
}
|
|
||||||
fn next_node(&self, node: &Node) -> Node {
|
|
||||||
Node {
|
|
||||||
pos: node.pos + self.offset(),
|
|
||||||
vertical_vel: VerticalVel::None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cost = WALK_ONE_BLOCK_COST + JUMP_COST;
|
||||||
|
|
||||||
|
Some(MoveResult {
|
||||||
|
node: Node {
|
||||||
|
pos: node.pos + offset,
|
||||||
|
vertical_vel: VerticalVel::None,
|
||||||
|
},
|
||||||
|
cost,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub struct DescendMove(pub CardinalDirection);
|
pub struct DescendMove(pub CardinalDirection);
|
||||||
impl Move for DescendMove {
|
impl Move for DescendMove {
|
||||||
fn cost(&self, world: &Instance, node: &Node) -> f32 {
|
fn get(&self, world: &Instance, node: &Node) -> Option<MoveResult> {
|
||||||
|
let new_horizontal_position = node.pos + BlockPos::new(self.0.x(), 0, self.0.z());
|
||||||
|
let fall_distance = fall_distance(&new_horizontal_position, world);
|
||||||
|
if fall_distance == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if fall_distance > 3 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let new_position = new_horizontal_position.down(fall_distance as i32);
|
||||||
|
|
||||||
// check whether 3 blocks vertically forward are passable
|
// check whether 3 blocks vertically forward are passable
|
||||||
if node.vertical_vel == VerticalVel::None
|
if node.vertical_vel != VerticalVel::None || !is_passable(&new_horizontal_position, world) {
|
||||||
&& is_standable(&(node.pos + self.offset()), world)
|
return None;
|
||||||
&& is_block_passable(&(node.pos + self.offset().up(2)), world)
|
|
||||||
{
|
|
||||||
WALK_ONE_BLOCK_COST
|
|
||||||
} else {
|
|
||||||
f32::INFINITY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn offset(&self) -> BlockPos {
|
|
||||||
BlockPos::new(self.0.x(), -1, self.0.z())
|
|
||||||
}
|
|
||||||
fn next_node(&self, node: &Node) -> Node {
|
|
||||||
Node {
|
|
||||||
pos: node.pos + self.offset(),
|
|
||||||
vertical_vel: VerticalVel::None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cost = WALK_ONE_BLOCK_COST + FALL_ONE_BLOCK_COST * fall_distance as f32;
|
||||||
|
|
||||||
|
Some(MoveResult {
|
||||||
|
node: Node {
|
||||||
|
pos: new_position,
|
||||||
|
vertical_vel: VerticalVel::None,
|
||||||
|
},
|
||||||
|
cost,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub struct DiagonalMove(pub CardinalDirection);
|
pub struct DiagonalMove(pub CardinalDirection);
|
||||||
impl Move for DiagonalMove {
|
impl Move for DiagonalMove {
|
||||||
fn cost(&self, world: &Instance, node: &Node) -> f32 {
|
fn get(&self, world: &Instance, node: &Node) -> Option<MoveResult> {
|
||||||
if node.vertical_vel != VerticalVel::None {
|
if node.vertical_vel != VerticalVel::None {
|
||||||
return f32::INFINITY;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let right = self.0.right();
|
||||||
|
let offset = BlockPos::new(self.0.x() + right.x(), 0, self.0.z() + right.z());
|
||||||
|
|
||||||
if !is_passable(
|
if !is_passable(
|
||||||
&BlockPos::new(node.pos.x + self.0.x(), node.pos.y, node.pos.z + self.0.z()),
|
&BlockPos::new(node.pos.x + self.0.x(), node.pos.y, node.pos.z + self.0.z()),
|
||||||
world,
|
world,
|
||||||
|
@ -128,22 +155,20 @@ impl Move for DiagonalMove {
|
||||||
),
|
),
|
||||||
world,
|
world,
|
||||||
) {
|
) {
|
||||||
return f32::INFINITY;
|
return None;
|
||||||
}
|
}
|
||||||
if !is_standable(&(node.pos + self.offset()), world) {
|
if !is_standable(&(node.pos + offset), world) {
|
||||||
return f32::INFINITY;
|
return None;
|
||||||
}
|
|
||||||
WALK_ONE_BLOCK_COST * 1.4
|
|
||||||
}
|
|
||||||
fn offset(&self) -> BlockPos {
|
|
||||||
let right = self.0.right();
|
|
||||||
BlockPos::new(self.0.x() + right.x(), 0, self.0.z() + right.z())
|
|
||||||
}
|
|
||||||
fn next_node(&self, node: &Node) -> Node {
|
|
||||||
Node {
|
|
||||||
pos: node.pos + self.offset(),
|
|
||||||
vertical_vel: VerticalVel::None,
|
|
||||||
}
|
}
|
||||||
|
let cost = WALK_ONE_BLOCK_COST * 1.4;
|
||||||
|
|
||||||
|
Some(MoveResult {
|
||||||
|
node: Node {
|
||||||
|
pos: node.pos + offset,
|
||||||
|
vertical_vel: VerticalVel::None,
|
||||||
|
},
|
||||||
|
cost,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue