mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 23:44:38 +00:00
optimize physics a bit more
This commit is contained in:
parent
e47dee388e
commit
4f288b1c03
7 changed files with 176 additions and 157 deletions
|
@ -3,9 +3,7 @@ use crate::position::BlockPos;
|
||||||
pub struct Cursor3d {
|
pub struct Cursor3d {
|
||||||
index: usize,
|
index: usize,
|
||||||
|
|
||||||
origin_x: i32,
|
origin: BlockPos,
|
||||||
origin_y: i32,
|
|
||||||
origin_z: i32,
|
|
||||||
|
|
||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
|
@ -14,6 +12,12 @@ pub struct Cursor3d {
|
||||||
end: usize,
|
end: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Cursor3d {
|
||||||
|
pub fn origin(&self) -> BlockPos {
|
||||||
|
self.origin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Iterator for Cursor3d {
|
impl Iterator for Cursor3d {
|
||||||
type Item = CursorIteration;
|
type Item = CursorIteration;
|
||||||
|
|
||||||
|
@ -40,9 +44,9 @@ impl Iterator for Cursor3d {
|
||||||
|
|
||||||
Some(CursorIteration {
|
Some(CursorIteration {
|
||||||
pos: BlockPos {
|
pos: BlockPos {
|
||||||
x: self.origin_x + x as i32,
|
x: self.origin.x + x as i32,
|
||||||
y: self.origin_y + y as i32,
|
y: self.origin.y + y as i32,
|
||||||
z: self.origin_z + z as i32,
|
z: self.origin.z + z as i32,
|
||||||
},
|
},
|
||||||
iteration_type: iteration_type.into(),
|
iteration_type: iteration_type.into(),
|
||||||
})
|
})
|
||||||
|
@ -64,30 +68,21 @@ pub struct CursorIteration {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cursor3d {
|
impl Cursor3d {
|
||||||
pub fn new(
|
pub fn new(origin: BlockPos, end: BlockPos) -> Self {
|
||||||
origin_x: i32,
|
let width = (end.x - origin.x + 1)
|
||||||
origin_y: i32,
|
|
||||||
origin_z: i32,
|
|
||||||
end_x: i32,
|
|
||||||
end_y: i32,
|
|
||||||
end_z: i32,
|
|
||||||
) -> Self {
|
|
||||||
let width = (end_x - origin_x + 1)
|
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("Impossible width.");
|
.expect("Impossible width.");
|
||||||
let height = (end_y - origin_y + 1)
|
let height = (end.y - origin.y + 1)
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("Impossible height.");
|
.expect("Impossible height.");
|
||||||
let depth = (end_z - origin_z + 1)
|
let depth = (end.z - origin.z + 1)
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("Impossible depth.");
|
.expect("Impossible depth.");
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
index: 0,
|
index: 0,
|
||||||
|
|
||||||
origin_x,
|
origin,
|
||||||
origin_y,
|
|
||||||
origin_z,
|
|
||||||
|
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
|
|
@ -410,7 +410,7 @@ pub struct PlayerBundle {
|
||||||
/// be updated by other clients.
|
/// be updated by other clients.
|
||||||
///
|
///
|
||||||
/// If this is for a client then all of our clients will have this.
|
/// If this is for a client then all of our clients will have this.
|
||||||
#[derive(Component)]
|
#[derive(Component, Clone)]
|
||||||
pub struct LocalEntity;
|
pub struct LocalEntity;
|
||||||
|
|
||||||
#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)]
|
#[derive(Component, Clone, Debug, PartialEq, Deref, DerefMut)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::cmp::Ordering;
|
use std::cmp::{self, Ordering};
|
||||||
|
|
||||||
use super::CubePointRange;
|
use super::CubePointRange;
|
||||||
use azalea_core::math::{gcd, lcm, EPSILON};
|
use azalea_core::math::{gcd, lcm, EPSILON};
|
||||||
|
@ -135,27 +135,27 @@ impl IndexMerger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_indirect(var1: &[f64], var2: &[f64], var3: bool, var4: bool) -> Self {
|
pub fn new_indirect(coords1: &[f64], coords2: &[f64], var3: bool, var4: bool) -> Self {
|
||||||
let mut var5 = f64::NAN;
|
let mut var5 = f64::NAN;
|
||||||
let var7 = var1.len();
|
let coords1_len = coords1.len();
|
||||||
let var8 = var2.len();
|
let coords2_len = coords2.len();
|
||||||
let var9 = var7 + var8;
|
let number_of_indices = coords1_len + coords2_len;
|
||||||
let mut result = vec![0.0; var9];
|
let mut result = vec![0.0; number_of_indices];
|
||||||
let mut first_indices: Vec<isize> = vec![0; var9];
|
let mut first_indices: Vec<isize> = vec![0; number_of_indices];
|
||||||
let mut second_indices: Vec<isize> = vec![0; var9];
|
let mut second_indices: Vec<isize> = vec![0; number_of_indices];
|
||||||
let var10 = !var3;
|
let var10 = !var3;
|
||||||
let var11 = !var4;
|
let var11 = !var4;
|
||||||
let mut var12 = 0;
|
let mut var12 = 0;
|
||||||
let mut var13 = 0;
|
let mut coords1_index = 0;
|
||||||
let mut var14 = 0;
|
let mut coords2_index = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut var17: bool;
|
let mut iterating_coords1: bool;
|
||||||
loop {
|
loop {
|
||||||
let var15 = var13 >= var7;
|
let at_end_of_coords1 = coords1_index >= coords1_len;
|
||||||
let var16 = var14 >= var8;
|
let at_end_of_coords2 = coords2_index >= coords2_len;
|
||||||
if var15 && var16 {
|
if at_end_of_coords1 && at_end_of_coords2 {
|
||||||
let result_length = std::cmp::max(1, var12);
|
let result_length = cmp::max(1, var12);
|
||||||
return Self::Indirect {
|
return Self::Indirect {
|
||||||
result,
|
result,
|
||||||
first_indices,
|
first_indices,
|
||||||
|
@ -164,26 +164,28 @@ impl IndexMerger {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var17 = !var15 && (var16 || var1[var13] < var2[var14] + EPSILON);
|
iterating_coords1 = !at_end_of_coords1
|
||||||
if var17 {
|
&& (at_end_of_coords2
|
||||||
var13 += 1;
|
|| coords1[coords1_index] < coords2[coords2_index] + EPSILON);
|
||||||
if !var10 || var14 != 0 && !var16 {
|
if iterating_coords1 {
|
||||||
|
coords1_index += 1;
|
||||||
|
if !var10 || coords2_index != 0 && !at_end_of_coords2 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var14 += 1;
|
coords2_index += 1;
|
||||||
if !var11 || var13 != 0 && !var15 {
|
if !var11 || coords1_index != 0 && !at_end_of_coords1 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let var18: isize = (var13 as isize) - 1;
|
let var18: isize = (coords1_index as isize) - 1;
|
||||||
let var19: isize = (var14 as isize) - 1;
|
let var19: isize = (coords2_index as isize) - 1;
|
||||||
let var20 = if var17 {
|
let var20 = if iterating_coords1 {
|
||||||
var1[TryInto::<usize>::try_into(var18).unwrap()]
|
coords1[usize::try_from(var18).unwrap()]
|
||||||
} else {
|
} else {
|
||||||
var2[TryInto::<usize>::try_into(var19).unwrap()]
|
coords2[usize::try_from(var19).unwrap()]
|
||||||
};
|
};
|
||||||
match var5.partial_cmp(&(var20 - EPSILON)) {
|
match var5.partial_cmp(&(var20 - EPSILON)) {
|
||||||
None | Some(Ordering::Less) => {
|
None | Some(Ordering::Less) => {
|
||||||
|
|
|
@ -266,7 +266,6 @@ fn collide_bounding_box(
|
||||||
|
|
||||||
let block_collisions =
|
let block_collisions =
|
||||||
get_block_collisions(world, entity_bounding_box.expand_towards(movement));
|
get_block_collisions(world, entity_bounding_box.expand_towards(movement));
|
||||||
let block_collisions = block_collisions.collect::<Vec<_>>();
|
|
||||||
collision_boxes.extend(block_collisions);
|
collision_boxes.extend(block_collisions);
|
||||||
collide_with_shapes(movement, *entity_bounding_box, &collision_boxes)
|
collide_with_shapes(movement, *entity_bounding_box, &collision_boxes)
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,22 +169,22 @@ impl Shapes {
|
||||||
// var5.getList(), var6.getList(), var7.getList()));
|
// var5.getList(), var6.getList(), var7.getList()));
|
||||||
let var5 = Self::create_index_merger(
|
let var5 = Self::create_index_merger(
|
||||||
1,
|
1,
|
||||||
a.get_coords(Axis::X).to_vec(),
|
a.get_coords(Axis::X),
|
||||||
b.get_coords(Axis::X).to_vec(),
|
b.get_coords(Axis::X),
|
||||||
op_true_false,
|
op_true_false,
|
||||||
op_false_true,
|
op_false_true,
|
||||||
);
|
);
|
||||||
let var6 = Self::create_index_merger(
|
let var6 = Self::create_index_merger(
|
||||||
(var5.size() - 1).try_into().unwrap(),
|
(var5.size() - 1).try_into().unwrap(),
|
||||||
a.get_coords(Axis::Y).to_vec(),
|
a.get_coords(Axis::Y),
|
||||||
b.get_coords(Axis::Y).to_vec(),
|
b.get_coords(Axis::Y),
|
||||||
op_true_false,
|
op_true_false,
|
||||||
op_false_true,
|
op_false_true,
|
||||||
);
|
);
|
||||||
let var7 = Self::create_index_merger(
|
let var7 = Self::create_index_merger(
|
||||||
((var5.size() - 1) * (var6.size() - 1)).try_into().unwrap(),
|
((var5.size() - 1) * (var6.size() - 1)).try_into().unwrap(),
|
||||||
a.get_coords(Axis::Z).to_vec(),
|
a.get_coords(Axis::Z),
|
||||||
b.get_coords(Axis::Z).to_vec(),
|
b.get_coords(Axis::Z),
|
||||||
op_true_false,
|
op_true_false,
|
||||||
op_false_true,
|
op_false_true,
|
||||||
);
|
);
|
||||||
|
@ -208,8 +208,12 @@ impl Shapes {
|
||||||
|
|
||||||
/// Check if the op is true anywhere when joining the two shapes
|
/// Check if the op is true anywhere when joining the two shapes
|
||||||
/// vanilla calls this joinIsNotEmpty
|
/// vanilla calls this joinIsNotEmpty
|
||||||
pub fn matches_anywhere(a: &VoxelShape, b: &VoxelShape, op: fn(bool, bool) -> bool) -> bool {
|
pub fn matches_anywhere(
|
||||||
assert!(!op(false, false));
|
a: &VoxelShape,
|
||||||
|
b: &VoxelShape,
|
||||||
|
op: impl Fn(bool, bool) -> bool,
|
||||||
|
) -> bool {
|
||||||
|
debug_assert!(!op(false, false));
|
||||||
let a_is_empty = a.is_empty();
|
let a_is_empty = a.is_empty();
|
||||||
let b_is_empty = b.is_empty();
|
let b_is_empty = b.is_empty();
|
||||||
if a_is_empty || b_is_empty {
|
if a_is_empty || b_is_empty {
|
||||||
|
@ -233,22 +237,22 @@ impl Shapes {
|
||||||
|
|
||||||
let x_merger = Self::create_index_merger(
|
let x_merger = Self::create_index_merger(
|
||||||
1,
|
1,
|
||||||
a.get_coords(Axis::X).to_vec(),
|
a.get_coords(Axis::X),
|
||||||
b.get_coords(Axis::X).to_vec(),
|
b.get_coords(Axis::X),
|
||||||
op_true_false,
|
op_true_false,
|
||||||
op_false_true,
|
op_false_true,
|
||||||
);
|
);
|
||||||
let y_merger = Self::create_index_merger(
|
let y_merger = Self::create_index_merger(
|
||||||
(x_merger.size() - 1) as i32,
|
(x_merger.size() - 1) as i32,
|
||||||
a.get_coords(Axis::Y).to_vec(),
|
a.get_coords(Axis::Y),
|
||||||
b.get_coords(Axis::Y).to_vec(),
|
b.get_coords(Axis::Y),
|
||||||
op_true_false,
|
op_true_false,
|
||||||
op_false_true,
|
op_false_true,
|
||||||
);
|
);
|
||||||
let z_merger = Self::create_index_merger(
|
let z_merger = Self::create_index_merger(
|
||||||
((x_merger.size() - 1) * (y_merger.size() - 1)) as i32,
|
((x_merger.size() - 1) * (y_merger.size() - 1)) as i32,
|
||||||
a.get_coords(Axis::Z).to_vec(),
|
a.get_coords(Axis::Z),
|
||||||
b.get_coords(Axis::Z).to_vec(),
|
b.get_coords(Axis::Z),
|
||||||
op_true_false,
|
op_true_false,
|
||||||
op_false_true,
|
op_false_true,
|
||||||
);
|
);
|
||||||
|
@ -269,7 +273,7 @@ impl Shapes {
|
||||||
merged_z: IndexMerger,
|
merged_z: IndexMerger,
|
||||||
shape1: DiscreteVoxelShape,
|
shape1: DiscreteVoxelShape,
|
||||||
shape2: DiscreteVoxelShape,
|
shape2: DiscreteVoxelShape,
|
||||||
op: fn(bool, bool) -> bool,
|
op: impl Fn(bool, bool) -> bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
!merged_x.for_merged_indexes(|var5x, var6, _var7| {
|
!merged_x.for_merged_indexes(|var5x, var6, _var7| {
|
||||||
merged_y.for_merged_indexes(|var6x, var7x, _var8| {
|
merged_y.for_merged_indexes(|var6x, var7x, _var8| {
|
||||||
|
@ -285,13 +289,13 @@ impl Shapes {
|
||||||
|
|
||||||
pub fn create_index_merger(
|
pub fn create_index_merger(
|
||||||
_var0: i32,
|
_var0: i32,
|
||||||
var1: Vec<f64>,
|
coords1: &[f64],
|
||||||
var2: Vec<f64>,
|
coords2: &[f64],
|
||||||
var3: bool,
|
var3: bool,
|
||||||
var4: bool,
|
var4: bool,
|
||||||
) -> IndexMerger {
|
) -> IndexMerger {
|
||||||
let var5 = var1.len() - 1;
|
let var5 = coords1.len() - 1;
|
||||||
let var6 = var2.len() - 1;
|
let var6 = coords2.len() - 1;
|
||||||
// if (&var1 as &dyn Any).is::<CubePointRange>() && (&var2 as &dyn
|
// if (&var1 as &dyn Any).is::<CubePointRange>() && (&var2 as &dyn
|
||||||
// Any).is::<CubePointRange>() {
|
// Any).is::<CubePointRange>() {
|
||||||
// return new DiscreteCubeMerger(var0, var5, var6, var3, var4);
|
// return new DiscreteCubeMerger(var0, var5, var6, var3, var4);
|
||||||
|
@ -302,22 +306,24 @@ impl Shapes {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if var1[var5] < var2[0] - EPSILON {
|
if coords1[var5] < coords2[0] - EPSILON {
|
||||||
IndexMerger::NonOverlapping {
|
IndexMerger::NonOverlapping {
|
||||||
lower: var1,
|
lower: coords1.to_vec(),
|
||||||
upper: var2,
|
upper: coords2.to_vec(),
|
||||||
swap: false,
|
swap: false,
|
||||||
}
|
}
|
||||||
} else if var2[var6] < var1[0] - EPSILON {
|
} else if coords2[var6] < coords1[0] - EPSILON {
|
||||||
IndexMerger::NonOverlapping {
|
IndexMerger::NonOverlapping {
|
||||||
lower: var2,
|
lower: coords2.to_vec(),
|
||||||
upper: var1,
|
upper: coords1.to_vec(),
|
||||||
swap: true,
|
swap: true,
|
||||||
}
|
}
|
||||||
} else if var5 == var6 && var1 == var2 {
|
} else if var5 == var6 && coords1 == coords2 {
|
||||||
IndexMerger::Identical { coords: var1 }
|
IndexMerger::Identical {
|
||||||
|
coords: coords1.to_vec(),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
IndexMerger::new_indirect(&var1, &var2, var3, var4)
|
IndexMerger::new_indirect(&coords1, &coords2, var3, var4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -386,6 +392,7 @@ impl VoxelShape {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn get(&self, axis: Axis, index: usize) -> f64 {
|
pub fn get(&self, axis: Axis, index: usize) -> f64 {
|
||||||
// self.get_coords(axis)[index]
|
// self.get_coords(axis)[index]
|
||||||
match self {
|
match self {
|
||||||
|
@ -403,9 +410,8 @@ impl VoxelShape {
|
||||||
match self {
|
match self {
|
||||||
VoxelShape::Cube(s) => s.find_index(axis, coord),
|
VoxelShape::Cube(s) => s.find_index(axis, coord),
|
||||||
_ => {
|
_ => {
|
||||||
binary_search(0, (self.shape().size(axis) + 1) as i32, &|t| {
|
let upper_limit = (self.shape().size(axis) + 1) as i32;
|
||||||
coord < self.get(axis, t as usize)
|
binary_search(0, upper_limit, &|t| coord < self.get(axis, t as usize)) - 1
|
||||||
}) - 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,6 +663,7 @@ impl ArrayVoxelShape {
|
||||||
&self.shape
|
&self.shape
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_coords(&self, axis: Axis) -> &[f64] {
|
fn get_coords(&self, axis: Axis) -> &[f64] {
|
||||||
axis.choose(&self.xs, &self.ys, &self.zs)
|
axis.choose(&self.xs, &self.ys, &self.zs)
|
||||||
}
|
}
|
||||||
|
@ -693,6 +700,7 @@ impl CubeVoxelShape {
|
||||||
parts
|
parts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_coords(&self, axis: Axis) -> &[f64] {
|
fn get_coords(&self, axis: Axis) -> &[f64] {
|
||||||
axis.choose(&self.x_coords, &self.y_coords, &self.z_coords)
|
axis.choose(&self.x_coords, &self.y_coords, &self.z_coords)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,79 @@ use azalea_block::BlockState;
|
||||||
use azalea_core::{
|
use azalea_core::{
|
||||||
cursor3d::{Cursor3d, CursorIterationType},
|
cursor3d::{Cursor3d, CursorIterationType},
|
||||||
math::EPSILON,
|
math::EPSILON,
|
||||||
position::{BlockPos, ChunkPos, ChunkSectionBlockPos, ChunkSectionPos},
|
position::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos, ChunkSectionPos},
|
||||||
};
|
};
|
||||||
use azalea_world::{Chunk, Instance};
|
use azalea_world::{Chunk, Instance};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub fn get_block_collisions(world: &Instance, aabb: AABB) -> BlockCollisions<'_> {
|
pub fn get_block_collisions(world: &Instance, aabb: AABB) -> Vec<VoxelShape> {
|
||||||
BlockCollisions::new(world, aabb)
|
let mut state = BlockCollisionsState::new(world, aabb);
|
||||||
|
let mut block_collisions = Vec::new();
|
||||||
|
|
||||||
|
let initial_chunk_pos = ChunkPos::from(state.cursor.origin());
|
||||||
|
let initial_chunk = world.chunks.get(&initial_chunk_pos).unwrap();
|
||||||
|
let initial_chunk = initial_chunk.read();
|
||||||
|
|
||||||
|
while let Some(item) = state.cursor.next() {
|
||||||
|
if item.iteration_type == CursorIterationType::Corner {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let item_chunk_pos = ChunkPos::from(item.pos);
|
||||||
|
let block_state: BlockState = if item_chunk_pos == initial_chunk_pos {
|
||||||
|
initial_chunk
|
||||||
|
.get(&ChunkBlockPos::from(item.pos), state.world.chunks.min_y)
|
||||||
|
.unwrap_or(BlockState::AIR)
|
||||||
|
} else {
|
||||||
|
state.get_block_state(item.pos)
|
||||||
|
};
|
||||||
|
|
||||||
|
if block_state.is_air() {
|
||||||
|
// fast path since we can't collide with air
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: continue if self.only_suffocating_blocks and the block is not
|
||||||
|
// suffocating
|
||||||
|
|
||||||
|
// if it's a full block do a faster collision check
|
||||||
|
if block_state.is_shape_full() {
|
||||||
|
if !state.aabb.intersects_aabb(&AABB {
|
||||||
|
min_x: item.pos.x as f64,
|
||||||
|
min_y: item.pos.y as f64,
|
||||||
|
min_z: item.pos.z as f64,
|
||||||
|
max_x: (item.pos.x + 1) as f64,
|
||||||
|
max_y: (item.pos.y + 1) as f64,
|
||||||
|
max_z: (item.pos.z + 1) as f64,
|
||||||
|
}) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
block_collisions.push(BLOCK_SHAPE.move_relative(
|
||||||
|
item.pos.x as f64,
|
||||||
|
item.pos.y as f64,
|
||||||
|
item.pos.z as f64,
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let block_shape = state.get_block_shape(block_state);
|
||||||
|
|
||||||
|
let block_shape =
|
||||||
|
block_shape.move_relative(item.pos.x as f64, item.pos.y as f64, item.pos.z as f64);
|
||||||
|
// if the entity shape and block shape don't collide, continue
|
||||||
|
if !Shapes::matches_anywhere(&block_shape, &state.entity_shape, |a, b| a && b) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
block_collisions.push(block_shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
block_collisions
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BlockCollisions<'a> {
|
pub struct BlockCollisionsState<'a> {
|
||||||
pub world: &'a Instance,
|
pub world: &'a Instance,
|
||||||
pub aabb: AABB,
|
pub aabb: AABB,
|
||||||
pub entity_shape: VoxelShape,
|
pub entity_shape: VoxelShape,
|
||||||
|
@ -25,17 +87,21 @@ pub struct BlockCollisions<'a> {
|
||||||
cached_block_shapes: Vec<(BlockState, &'static VoxelShape)>,
|
cached_block_shapes: Vec<(BlockState, &'static VoxelShape)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BlockCollisions<'a> {
|
impl<'a> BlockCollisionsState<'a> {
|
||||||
pub fn new(world: &'a Instance, aabb: AABB) -> Self {
|
pub fn new(world: &'a Instance, aabb: AABB) -> Self {
|
||||||
let origin_x = (aabb.min_x - EPSILON).floor() as i32 - 1;
|
let origin = BlockPos {
|
||||||
let origin_y = (aabb.min_y - EPSILON).floor() as i32 - 1;
|
x: (aabb.min_x - EPSILON).floor() as i32 - 1,
|
||||||
let origin_z = (aabb.min_z - EPSILON).floor() as i32 - 1;
|
y: (aabb.min_y - EPSILON).floor() as i32 - 1,
|
||||||
|
z: (aabb.min_z - EPSILON).floor() as i32 - 1,
|
||||||
|
};
|
||||||
|
|
||||||
let end_x = (aabb.max_x + EPSILON).floor() as i32 + 1;
|
let end = BlockPos {
|
||||||
let end_y = (aabb.max_y + EPSILON).floor() as i32 + 1;
|
x: (aabb.max_x + EPSILON).floor() as i32 + 1,
|
||||||
let end_z = (aabb.max_z + EPSILON).floor() as i32 + 1;
|
y: (aabb.max_y + EPSILON).floor() as i32 + 1,
|
||||||
|
z: (aabb.max_z + EPSILON).floor() as i32 + 1,
|
||||||
|
};
|
||||||
|
|
||||||
let cursor = Cursor3d::new(origin_x, origin_y, origin_z, end_x, end_y, end_z);
|
let cursor = Cursor3d::new(origin, end);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
world,
|
world,
|
||||||
|
@ -97,10 +163,8 @@ impl<'a> BlockCollisions<'a> {
|
||||||
|
|
||||||
self.cached_sections.push((section_pos, section.clone()));
|
self.cached_sections.push((section_pos, section.clone()));
|
||||||
|
|
||||||
// println!(
|
// println!("chunk section palette: {:?}", section.states.palette);
|
||||||
// "chunk section length: {}",
|
// println!("chunk section data: {:?}", section.states.storage.data);
|
||||||
// section.states.storage.data.len()
|
|
||||||
// );
|
|
||||||
// println!("biome length: {}", section.biomes.storage.data.len());
|
// println!("biome length: {}", section.biomes.storage.data.len());
|
||||||
|
|
||||||
section.get(section_block_pos)
|
section.get(section_block_pos)
|
||||||
|
@ -119,58 +183,3 @@ impl<'a> BlockCollisions<'a> {
|
||||||
shape
|
shape
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for BlockCollisions<'a> {
|
|
||||||
type Item = VoxelShape;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
while let Some(item) = self.cursor.next() {
|
|
||||||
if item.iteration_type == CursorIterationType::Corner {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let block_state = self.get_block_state(item.pos);
|
|
||||||
|
|
||||||
if block_state.is_air() {
|
|
||||||
// fast path since we can't collide with air
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: continue if self.only_suffocating_blocks and the block is not
|
|
||||||
// suffocating
|
|
||||||
|
|
||||||
// if it's a full block do a faster collision check
|
|
||||||
if block_state.is_shape_full() {
|
|
||||||
if !self.aabb.intersects_aabb(&AABB {
|
|
||||||
min_x: item.pos.x as f64,
|
|
||||||
min_y: item.pos.y as f64,
|
|
||||||
min_z: item.pos.z as f64,
|
|
||||||
max_x: (item.pos.x + 1) as f64,
|
|
||||||
max_y: (item.pos.y + 1) as f64,
|
|
||||||
max_z: (item.pos.z + 1) as f64,
|
|
||||||
}) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Some(BLOCK_SHAPE.move_relative(
|
|
||||||
item.pos.x as f64,
|
|
||||||
item.pos.y as f64,
|
|
||||||
item.pos.z as f64,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let block_shape = self.get_block_shape(block_state);
|
|
||||||
|
|
||||||
let block_shape =
|
|
||||||
block_shape.move_relative(item.pos.x as f64, item.pos.y as f64, item.pos.z as f64);
|
|
||||||
// if the entity shape and block shape don't collide, continue
|
|
||||||
if !Shapes::matches_anywhere(&block_shape, &self.entity_shape, |a, b| a && b) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Some(block_shape);
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -87,14 +87,13 @@ fn create_simulation_instance(chunks: ChunkStorage) -> (App, Arc<RwLock<Instance
|
||||||
(app, instance)
|
(app, instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_simulation_player(
|
fn create_simulation_player_complete_bundle(
|
||||||
ecs: &mut World,
|
|
||||||
instance: Arc<RwLock<Instance>>,
|
instance: Arc<RwLock<Instance>>,
|
||||||
player: SimulatedPlayerBundle,
|
player: &SimulatedPlayerBundle,
|
||||||
) -> Entity {
|
) -> impl Bundle {
|
||||||
let instance_name = simulation_instance_name();
|
let instance_name = simulation_instance_name();
|
||||||
|
|
||||||
let mut entity = ecs.spawn((
|
(
|
||||||
MinecraftEntityId(0),
|
MinecraftEntityId(0),
|
||||||
azalea_entity::LocalEntity,
|
azalea_entity::LocalEntity,
|
||||||
azalea_entity::metadata::PlayerMetadataBundle::default(),
|
azalea_entity::metadata::PlayerMetadataBundle::default(),
|
||||||
|
@ -110,9 +109,16 @@ fn create_simulation_player(
|
||||||
instance: instance.clone(),
|
instance: instance.clone(),
|
||||||
},
|
},
|
||||||
InventoryComponent::default(),
|
InventoryComponent::default(),
|
||||||
));
|
)
|
||||||
entity.insert(player);
|
}
|
||||||
|
|
||||||
|
fn create_simulation_player(
|
||||||
|
ecs: &mut World,
|
||||||
|
instance: Arc<RwLock<Instance>>,
|
||||||
|
player: SimulatedPlayerBundle,
|
||||||
|
) -> Entity {
|
||||||
|
let mut entity = ecs.spawn(create_simulation_player_complete_bundle(instance, &player));
|
||||||
|
entity.insert(player);
|
||||||
entity.id()
|
entity.id()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue