diff options
| author | mat <git@matdoes.dev> | 2023-10-02 18:53:27 -0500 |
|---|---|---|
| committer | mat <git@matdoes.dev> | 2023-10-02 18:53:27 -0500 |
| commit | 7b10e5cd7e80be85f7b0517f941b175e733d3fc4 (patch) | |
| tree | 1c99d6f4670456da4792f5c6be369662676ddd82 | |
| parent | d0505f7de30e4a9a330ef99d0082849ee44723e0 (diff) | |
| download | azalea-drasl-7b10e5cd7e80be85f7b0517f941b175e733d3fc4.tar.xz | |
optimize pathfinder more
| -rwxr-xr-x | azalea-brigadier/src/suggestion/mod.rs | 2 | ||||
| -rwxr-xr-x | azalea-core/src/position.rs | 14 | ||||
| -rw-r--r-- | azalea-physics/src/collision/blocks.rs | 14 | ||||
| -rw-r--r-- | azalea/src/pathfinder/moves/mod.rs | 4 | ||||
| -rw-r--r-- | azalea/src/pathfinder/moves/parkour.rs | 27 | ||||
| -rwxr-xr-x | codegen/lib/code/shapes.py | 63 |
6 files changed, 89 insertions, 35 deletions
diff --git a/azalea-brigadier/src/suggestion/mod.rs b/azalea-brigadier/src/suggestion/mod.rs index 22257423..c404adc7 100755 --- a/azalea-brigadier/src/suggestion/mod.rs +++ b/azalea-brigadier/src/suggestion/mod.rs @@ -1,5 +1,5 @@ mod suggestions; - mod suggestions_builder; +mod suggestions_builder; use crate::context::StringRange; #[cfg(feature = "azalea-buf")] diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index 09ed44fd..16578517 100755 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -15,28 +15,33 @@ use crate::resource_location::ResourceLocation; macro_rules! vec3_impl { ($name:ident, $type:ty) => { impl $name { + #[inline] pub fn new(x: $type, y: $type, z: $type) -> Self { Self { x, y, z } } /// Get the distance of this vector to the origin by doing `x^2 + y^2 + /// z^2`. + #[inline] pub fn length_sqr(&self) -> $type { self.x * self.x + self.y * self.y + self.z * self.z } /// Get the squared distance from this position to another position. /// Equivalent to `(self - other).length_sqr()`. + #[inline] pub fn distance_to_sqr(&self, other: &Self) -> $type { (self - other).length_sqr() } + #[inline] pub fn horizontal_distance_sqr(&self) -> $type { self.x * self.x + self.z * self.z } /// Return a new instance of this position with the y coordinate /// decreased by the given number. + #[inline] pub fn down(&self, y: $type) -> Self { Self { x: self.x, @@ -46,6 +51,7 @@ macro_rules! vec3_impl { } /// Return a new instance of this position with the y coordinate /// increased by the given number. + #[inline] pub fn up(&self, y: $type) -> Self { Self { x: self.x, @@ -54,6 +60,7 @@ macro_rules! vec3_impl { } } + #[inline] pub fn dot(&self, other: Self) -> $type { self.x * other.x + self.y * other.y + self.z * other.z } @@ -62,6 +69,7 @@ macro_rules! vec3_impl { impl Add for &$name { type Output = $name; + #[inline] fn add(self, rhs: Self) -> Self::Output { $name { x: self.x + rhs.x, @@ -74,12 +82,14 @@ macro_rules! vec3_impl { impl Add for $name { type Output = $name; + #[inline] fn add(self, rhs: Self) -> Self::Output { (&self).add(&rhs) } } impl AddAssign for $name { + #[inline] fn add_assign(&mut self, rhs: Self) { self.x += rhs.x; self.y += rhs.y; @@ -89,6 +99,7 @@ macro_rules! vec3_impl { impl Rem<$type> for $name { type Output = Self; + #[inline] fn rem(self, rhs: $type) -> Self::Output { Self { x: self.x % rhs, @@ -102,6 +113,7 @@ macro_rules! vec3_impl { type Output = $name; /// Find the difference between two positions. + #[inline] fn sub(self, other: Self) -> Self::Output { Self::Output { x: self.x - other.x, @@ -113,6 +125,7 @@ macro_rules! vec3_impl { impl Sub for $name { type Output = Self; + #[inline] fn sub(self, other: Self) -> Self::Output { (&self).sub(&other) } @@ -121,6 +134,7 @@ macro_rules! vec3_impl { impl Mul<$type> for $name { type Output = Self; + #[inline] fn mul(self, multiplier: $type) -> Self::Output { Self { x: self.x * multiplier, diff --git a/azalea-physics/src/collision/blocks.rs b/azalea-physics/src/collision/blocks.rs index dfe322b7..f6baea9f 100644 --- a/azalea-physics/src/collision/blocks.rs +++ b/azalea-physics/src/collision/blocks.rs @@ -13,6 +13,12 @@ use once_cell::sync::Lazy; pub trait BlockWithShape { fn shape(&self) -> &'static VoxelShape; + /// Tells you whether the block has an empty shape. + /// + /// This is slightly more efficient than calling `shape()` and comparing + /// against `EMPTY_SHAPE`. + fn is_shape_empty(&self) -> bool; + fn is_shape_full(&self) -> bool; } static SHAPE0: Lazy<VoxelShape> = Lazy::new(|| collision::EMPTY_SHAPE.clone()); @@ -8028,4 +8034,12 @@ impl BlockWithShape for BlockState { _ => &SHAPE1, } } + + fn is_shape_empty(&self) -> bool { + matches!(self.id, 0|25..=78|80..=111|1944..=1991|2004..=2010|2063..=2090|2355..=2872|2978..=4273|4278..=4285|4302..=4589|4662..=4681|4762..=5537|5626..=5651|5716..=5733|5738..=5772|5799..=5814|5859..=5863|5865..=5866|6813..=6998|7001..=7002|7005..=7006|7009..=7010|7013..=7014|7017..=7018|7021..=7022|7025..=7026|7385..=7388|7406|7521..=7664|7925|7928|8249|8252|8595..=8826|9143..=9174|9320..=9343|10367..=10398|10747..=11078|11310..=11311|11314..=11315|11318..=11319|11322..=11323|11326..=11327|11330..=11331|11334..=11335|11338..=11339|11342..=11343|11346..=11347|11350..=11351|11354..=11355|11358..=11359|11362..=11363|11366..=11367|11370..=11371|11374..=11375|11378..=11379|11382..=11383|11386..=11387|11390..=11391|11394..=11395|11398..=11399|11402..=11403|11406..=11407|11410..=11411|11414..=11415|11418..=11419|11422..=11423|11426..=11427|11430..=11431|11434..=11435|11438..=11439|11442..=11443|11446..=11447|11450..=11451|11454..=11455|11458..=11459|11462..=11463|11466..=11467|11470..=11471|11474..=11475|11478..=11479|11482..=11483|11486..=11487|11490..=11491|11494..=11495|11498..=11499|11502..=11503|11506..=11507|11510..=11511|11514..=11515|11518..=11519|11522..=11523|11526..=11527|11530..=11531|11534..=11535|11538..=11539|11542..=11543|11546..=11547|11550..=11551|11554..=11555|11558..=11559|11562..=11563|12495..=12496|12499|12501|12503|12505|12507..=12512|12514|12549|12760..=12786|12813..=12932|12944|12958..=12961|14166|14169|14490|14493|14814|14817|15138|15141|15462|15465|15786|15789|16110|16113|16434|16437|16758|16761|17082|17085|17406|17409|17730|17733|18054|18057|18575..=18578|18592|18594..=18595|18609|18611..=18665|18680..=18683|18876..=18877|18880..=18881|18884..=18885|18888..=18889|18892..=18893|18896..=18897|18900..=18901|18904..=18905|18908..=18909|18912..=18913|18916..=18917|18920..=18921|18924..=18925|18928..=18929|18932..=18933|18936..=18937|19100..=19147|19276..=19355|19547|19550|19967|19970|20372..=20397|20404|20407|21084|21566..=21693|22455..=22509|22513..=22528|22536..=22537|22544..=22545|22552..=22553|22560..=22587|22686|22689|23097|23100|23508|23511|23919|23922|24258) + } + + fn is_shape_full(&self) -> bool { + matches!(self.id, 1..=24|79|112..=1687|1998..=2003|2017..=2022|2047..=2062|2091..=2354|2873|4274..=4277|4294..=4301|5734..=5737|5780..=5781|5798|5815..=5816|5849..=5850|5852..=5858|5864|5867..=5874|5946..=5961|6538..=6741|6812|7269..=7270|7272|7415|7417..=7418|7511..=7512|7665|7906..=7918|9223..=9224|9235..=9239|9344..=9371|10364..=10366|10463..=10465|10710..=10711|10716..=10717|10722..=10727|10744..=10746|11079..=11081|11166..=11167|11172..=11173|11178..=11179|11184..=11185|11190..=11191|11196..=11197|11202..=11203|11208..=11209|11214..=11215|11220..=11221|11226..=11227|11232..=11233|11238..=11239|11244..=11245|11250..=11251|11256..=11257|11262..=11263|11268..=11269|11274..=11275|11280..=11281|11286..=11287|11292..=11293|11298..=11299|11304..=11309|12404..=12413|12494|12515..=12548|12550..=12759|12787|12803..=12812|12941|14086..=14087|14092..=14093|14098..=14099|14104..=14105|14110..=14111|14116..=14117|14122..=14123|14128..=14129|14134..=14135|14140..=14141|14146..=14147|14152..=14153|14158..=14159|18404..=18437|18466|18579..=18591|18593|18596..=18608|18610|18666..=18667|18672..=18673|18678..=18679|19356..=19371|19381..=19444|19446..=19454|19459..=19460|19869..=19874|19879..=19880|20285|20370..=20371|20722..=20724|21031..=21032|21081..=21083|21565|21694..=21695|21704..=21713|22038..=22039|22044..=22045|22050..=22051|22056..=22065|22390..=22391|22396..=22397|22402..=22403|22408..=22409|22454|22529|22588|22590..=22593|22678..=22679|23004|23089..=23090|23415|23500..=23501|23826|23911..=23912|24237..=24246|24249..=24257|24259) + } } diff --git a/azalea/src/pathfinder/moves/mod.rs b/azalea/src/pathfinder/moves/mod.rs index caf4bbb4..9eb6462b 100644 --- a/azalea/src/pathfinder/moves/mod.rs +++ b/azalea/src/pathfinder/moves/mod.rs @@ -80,7 +80,7 @@ impl<'a> PathfinderCtx<'a> { // fast path return true; } - if block.shape() != &*collision::EMPTY_SHAPE { + if !block.is_shape_empty() { return false; } if block == azalea_registry::Block::Water.into() { @@ -107,7 +107,7 @@ impl<'a> PathfinderCtx<'a> { // fast path return false; } - block.shape() == &*collision::BLOCK_SHAPE + block.is_shape_full() } /// Whether this block and the block above are passable diff --git a/azalea/src/pathfinder/moves/parkour.rs b/azalea/src/pathfinder/moves/parkour.rs index 53f5a348..27763257 100644 --- a/azalea/src/pathfinder/moves/parkour.rs +++ b/azalea/src/pathfinder/moves/parkour.rs @@ -22,6 +22,10 @@ fn parkour_forward_1_move(ctx: &PathfinderCtx, pos: BlockPos) -> Vec<Edge> { let gap_offset = BlockPos::new(dir.x(), 0, dir.z()); let offset = BlockPos::new(dir.x() * 2, 0, dir.z() * 2); + // make sure we actually have to jump + if ctx.is_block_solid(&(pos + gap_offset).down(1)) { + continue; + } if !ctx.is_standable(&(pos + offset)) { continue; } @@ -31,10 +35,6 @@ fn parkour_forward_1_move(ctx: &PathfinderCtx, pos: BlockPos) -> Vec<Edge> { if !ctx.is_block_passable(&(pos + gap_offset).up(2)) { continue; } - // make sure we actually have to jump - if ctx.is_block_solid(&(pos + gap_offset).down(1)) { - continue; - } // make sure it's not a headhitter if !ctx.is_block_passable(&pos.up(2)) { continue; @@ -64,6 +64,13 @@ fn parkour_forward_2_move(ctx: &PathfinderCtx, pos: BlockPos) -> Vec<Edge> { let gap_2_offset = BlockPos::new(dir.x() * 2, 0, dir.z() * 2); let offset = BlockPos::new(dir.x() * 3, 0, dir.z() * 3); + // make sure we actually have to jump + if ctx.is_block_solid(&(pos + gap_1_offset).down(1)) + || ctx.is_block_solid(&(pos + gap_2_offset).down(1)) + { + continue; + } + if !ctx.is_standable(&(pos + offset)) { continue; } @@ -79,10 +86,6 @@ fn parkour_forward_2_move(ctx: &PathfinderCtx, pos: BlockPos) -> Vec<Edge> { if !ctx.is_block_passable(&(pos + gap_2_offset).up(2)) { continue; } - // make sure we actually have to jump - if ctx.is_block_solid(&(pos + gap_1_offset).down(1)) { - continue; - } // make sure it's not a headhitter if !ctx.is_block_passable(&pos.up(2)) { continue; @@ -114,6 +117,10 @@ fn parkour_headhitter_forward_1_move(ctx: &PathfinderCtx, pos: BlockPos) -> Vec< let gap_offset = BlockPos::new(dir.x(), 0, dir.z()); let offset = BlockPos::new(dir.x() * 2, 0, dir.z() * 2); + // make sure we actually have to jump + if ctx.is_block_solid(&(pos + gap_offset).down(1)) { + continue; + } if !ctx.is_standable(&(pos + offset)) { continue; } @@ -123,10 +130,6 @@ fn parkour_headhitter_forward_1_move(ctx: &PathfinderCtx, pos: BlockPos) -> Vec< if !ctx.is_block_passable(&(pos + gap_offset).up(2)) { continue; } - // make sure we actually have to jump - if ctx.is_block_solid(&(pos + gap_offset).down(1)) { - continue; - } // make sure it is a headhitter if !ctx.is_block_solid(&pos.up(2)) { continue; diff --git a/codegen/lib/code/shapes.py b/codegen/lib/code/shapes.py index f270fd7f..6906328c 100755 --- a/codegen/lib/code/shapes.py +++ b/codegen/lib/code/shapes.py @@ -72,6 +72,7 @@ def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report, for (shape_id, shape) in sorted(shapes.items(), key=lambda shape: int(shape[0])): generated_shape_code += generate_code_for_shape(shape_id, shape) + # 1..100 | 200..300 => &SHAPE1, generated_match_inner_code = '' shape_ids_to_block_state_ids = {} @@ -79,7 +80,6 @@ def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report, if isinstance(shape_ids, int): shape_ids = [shape_ids] block_report_data = block_states_report['minecraft:' + block_id] - block_data_burger = block_datas_burger[block_id] for possible_state, shape_id in zip(block_report_data['states'], shape_ids): block_state_id = possible_state['id'] @@ -87,30 +87,20 @@ def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report, if shape_id not in shape_ids_to_block_state_ids: shape_ids_to_block_state_ids[shape_id] = [] shape_ids_to_block_state_ids[shape_id].append(block_state_id) + + empty_shape_match_code = convert_ints_to_rust_ranges(shape_ids_to_block_state_ids[0]) + block_shape_match_code = convert_ints_to_rust_ranges(shape_ids_to_block_state_ids[1]) + # shape 1 is the most common so we have a _ => &SHAPE1 at the end del shape_ids_to_block_state_ids[1] - for shape_id, block_state_ids in shape_ids_to_block_state_ids.items(): - - # convert them into ranges (so like 1|2|3 is 1..=3 instead) - block_state_ids_ranges = [] - range_start_block_state_id = None - last_block_state_id = None - for block_state_id in sorted(block_state_ids): - if range_start_block_state_id is None: - range_start_block_state_id = block_state_id - - if last_block_state_id is not None: - # check if the range is done - if block_state_id - 1 != last_block_state_id: - block_state_ids_ranges.append(f'{range_start_block_state_id}..={last_block_state_id}' if range_start_block_state_id != last_block_state_id else str(range_start_block_state_id)) - range_start_block_state_id = block_state_id - - last_block_state_id = block_state_id - block_state_ids_ranges.append(f'{range_start_block_state_id}..={last_block_state_id}' if range_start_block_state_id != last_block_state_id else str(range_start_block_state_id)) - generated_match_inner_code += f'{"|".join(block_state_ids_ranges)} => &SHAPE{shape_id},\n' + for shape_id, block_state_ids in shape_ids_to_block_state_ids.items(): + generated_match_inner_code += f'{convert_ints_to_rust_ranges(block_state_ids)} => &SHAPE{shape_id},\n' generated_match_inner_code += '_ => &SHAPE1' + if empty_shape_match_code == '': + print('Error: shape 0 was not found') + return f''' //! Autogenerated block collisions for every block @@ -127,6 +117,11 @@ use once_cell::sync::Lazy; pub trait BlockWithShape {{ fn shape(&self) -> &'static VoxelShape; + /// Tells you whether the block has an empty shape. + /// + /// This is slightly more efficient than calling `shape()` and comparing against `EMPTY_SHAPE`. + fn is_shape_empty(&self) -> bool; + fn is_shape_full(&self) -> bool; }} {generated_shape_code} @@ -137,6 +132,14 @@ impl BlockWithShape for BlockState {{ {generated_match_inner_code} }} }} + + fn is_shape_empty(&self) -> bool {{ + matches!(self.id, {empty_shape_match_code}) + }} + + fn is_shape_full(&self) -> bool {{ + matches!(self.id, {block_shape_match_code}) + }} }} ''' @@ -165,3 +168,23 @@ def generate_code_for_shape(shape_id: str, parts: list[list[float]]): code += '}\n' code += '});\n' return code + +def convert_ints_to_rust_ranges(block_state_ids: list[int]) -> str: + # convert them into ranges (so like 1|2|3 is 1..=3 instead) + block_state_ids_ranges = [] + range_start_block_state_id = None + last_block_state_id = None + for block_state_id in sorted(block_state_ids): + if range_start_block_state_id is None: + range_start_block_state_id = block_state_id + + if last_block_state_id is not None: + # check if the range is done + if block_state_id - 1 != last_block_state_id: + block_state_ids_ranges.append(f'{range_start_block_state_id}..={last_block_state_id}' if range_start_block_state_id != last_block_state_id else str(range_start_block_state_id)) + range_start_block_state_id = block_state_id + + last_block_state_id = block_state_id + + block_state_ids_ranges.append(f'{range_start_block_state_id}..={last_block_state_id}' if range_start_block_state_id != last_block_state_id else str(range_start_block_state_id)) + return '|'.join(block_state_ids_ranges) |
