From 0d004b72ac22641978c6ef93ca8641eb621e2f48 Mon Sep 17 00:00:00 2001 From: mat <27899617+mat-1@users.noreply.github.com> Date: Tue, 15 Nov 2022 14:52:26 -0600 Subject: Rename "dimension" to "world" (#39) * rename "dimension" to "world" * Update mod.rs --- azalea-client/src/client.rs | 78 ++++++------ azalea-client/src/movement.rs | 8 +- azalea-client/src/player.rs | 18 +-- azalea-core/src/position.rs | 8 +- .../src/collision/dimension_collisions.rs | 139 --------------------- azalea-physics/src/collision/mod.rs | 22 ++-- azalea-physics/src/collision/world_collisions.rs | 139 +++++++++++++++++++++ azalea-physics/src/lib.rs | 70 ++++++----- azalea-world/src/chunk_storage.rs | 4 +- azalea-world/src/entity/mod.rs | 46 +++---- azalea-world/src/lib.rs | 17 ++- azalea/examples/potatobot/main.rs | 2 +- azalea/examples/pvp.rs | 5 +- azalea/src/pathfinder/mod.rs | 4 +- azalea/src/pathfinder/moves.rs | 93 +++++++------- bot/src/main.rs | 2 +- 16 files changed, 330 insertions(+), 325 deletions(-) delete mode 100755 azalea-physics/src/collision/dimension_collisions.rs create mode 100644 azalea-physics/src/collision/world_collisions.rs diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 296a967b..85e5013e 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -29,7 +29,7 @@ use azalea_protocol::{ }; use azalea_world::{ entity::{metadata, Entity, EntityData, EntityMetadata}, - Dimension, + World, }; use log::{debug, error, info, warn}; use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard}; @@ -87,7 +87,7 @@ pub struct Client { pub read_conn: Arc>>, pub write_conn: Arc>>, pub player: Arc>, - pub dimension: Arc>, + pub world: Arc>, pub physics_state: Arc>, pub client_information: Arc>, /// Plugins are a way for other crates to add custom functionality to the @@ -262,7 +262,7 @@ impl Client { read_conn, write_conn, player: Arc::new(RwLock::new(Player::default())), - dimension: Arc::new(RwLock::new(Dimension::default())), + world: Arc::new(RwLock::new(World::default())), physics_state: Arc::new(Mutex::new(PhysicsState::default())), client_information: Arc::new(RwLock::new(ClientInformation::default())), // The plugins can be modified by the user by replacing the plugins @@ -414,17 +414,17 @@ impl Client { .as_int() .expect("min_y tag is not an int"); - let mut dimension_lock = client.dimension.write(); + let mut world_lock = client.world.write(); // the 16 here is our render distance // i'll make this an actual setting later - *dimension_lock = Dimension::new(16, height, min_y); + *world_lock = World::new(16, height, min_y); let entity = EntityData::new( client.game_profile.uuid, Vec3::default(), EntityMetadata::Player(metadata::Player::default()), ); - dimension_lock.add_entity(p.player_id, entity); + world_lock.add_entity(p.player_id, entity); let mut player_lock = client.player.write(); @@ -497,9 +497,9 @@ impl Client { player_lock.entity_id }; - let mut dimension_lock = client.dimension.write(); + let mut world_lock = client.world.write(); - let mut player_entity = dimension_lock + let mut player_entity = world_lock .entity_mut(player_entity_id) .expect("Player entity doesn't exist"); @@ -553,7 +553,7 @@ impl Client { y: new_pos_y, z: new_pos_z, }; - dimension_lock + world_lock .set_entity_pos(player_entity_id, new_pos) .expect("The player entity should always exist"); @@ -584,7 +584,7 @@ impl Client { ClientboundGamePacket::SetChunkCacheCenter(p) => { debug!("Got chunk cache center packet {:?}", p); client - .dimension + .world .write() .update_view_center(&ChunkPos::new(p.x, p.z)); } @@ -594,7 +594,7 @@ impl Client { // let chunk = Chunk::read_with_world_height(&mut p.chunk_data); // debug("chunk {:?}") if let Err(e) = client - .dimension + .world .write() .replace_with_packet_data(&pos, &mut Cursor::new(&p.chunk_data.data)) { @@ -607,12 +607,12 @@ impl Client { ClientboundGamePacket::AddEntity(p) => { debug!("Got add entity packet {:?}", p); let entity = EntityData::from(p); - client.dimension.write().add_entity(p.id, entity); + client.world.write().add_entity(p.id, entity); } ClientboundGamePacket::SetEntityData(p) => { debug!("Got set entity data packet {:?}", p); - let mut dimension = client.dimension.write(); - if let Some(mut entity) = dimension.entity_mut(p.id) { + let mut world = client.world.write(); + if let Some(mut entity) = world.entity_mut(p.id) { entity.apply_metadata(&p.packed_items.0); } else { warn!("Server sent an entity data packet for an entity id ({}) that we don't know about", p.id); @@ -630,7 +630,7 @@ impl Client { ClientboundGamePacket::AddPlayer(p) => { debug!("Got add player packet {:?}", p); let entity = EntityData::from(p); - client.dimension.write().add_entity(p.id, entity); + client.world.write().add_entity(p.id, entity); } ClientboundGamePacket::InitializeBorder(p) => { debug!("Got initialize border packet {:?}", p); @@ -651,9 +651,9 @@ impl Client { debug!("Got set experience packet {:?}", p); } ClientboundGamePacket::TeleportEntity(p) => { - let mut dimension_lock = client.dimension.write(); + let mut world_lock = client.world.write(); - dimension_lock + world_lock .set_entity_pos( p.id, Vec3 { @@ -671,16 +671,16 @@ impl Client { // debug!("Got rotate head packet {:?}", p); } ClientboundGamePacket::MoveEntityPos(p) => { - let mut dimension_lock = client.dimension.write(); + let mut world_lock = client.world.write(); - dimension_lock + world_lock .move_entity_with_delta(p.entity_id, &p.delta) .map_err(|e| HandleError::Other(e.into()))?; } ClientboundGamePacket::MoveEntityPosRot(p) => { - let mut dimension_lock = client.dimension.write(); + let mut world_lock = client.world.write(); - dimension_lock + world_lock .move_entity_with_delta(p.entity_id, &p.delta) .map_err(|e| HandleError::Other(e.into()))?; } @@ -713,17 +713,17 @@ impl Client { } ClientboundGamePacket::BlockUpdate(p) => { debug!("Got block update packet {:?}", p); - let mut dimension = client.dimension.write(); - dimension.set_block_state(&p.pos, p.block_state); + let mut world = client.world.write(); + world.set_block_state(&p.pos, p.block_state); } ClientboundGamePacket::Animate(p) => { debug!("Got animate packet {:?}", p); } ClientboundGamePacket::SectionBlocksUpdate(p) => { debug!("Got section blocks update packet {:?}", p); - let mut dimension = client.dimension.write(); + let mut world = client.world.write(); for state in &p.states { - dimension.set_block_state(&(p.section_pos + state.pos.clone()), state.state); + world.set_block_state(&(p.section_pos + state.pos.clone()), state.state); } } ClientboundGamePacket::GameEvent(p) => { @@ -819,16 +819,16 @@ impl Client { async fn game_tick(client: &mut Client, tx: &UnboundedSender) { // return if there's no chunk at the player's position { - let dimension_lock = client.dimension.write(); + let world_lock = client.world.write(); let player_lock = client.player.write(); - let player_entity = player_lock.entity(&dimension_lock); + let player_entity = player_lock.entity(&world_lock); let player_entity = if let Some(player_entity) = player_entity { player_entity } else { return; }; let player_chunk_pos: ChunkPos = player_entity.pos().into(); - if dimension_lock[&player_chunk_pos].is_none() { + if world_lock[&player_chunk_pos].is_none() { return; } } @@ -846,43 +846,43 @@ impl Client { } /// Returns the entity associated to the player. - pub fn entity_mut(&self) -> Entity> { + pub fn entity_mut(&self) -> Entity> { let entity_id = { let player_lock = self.player.write(); player_lock.entity_id }; - let mut dimension = self.dimension.write(); + let mut world = self.world.write(); - let entity_data = dimension + let entity_data = world .entity_storage .get_mut_by_id(entity_id) .expect("Player entity should exist"); let entity_ptr = unsafe { entity_data.as_ptr() }; - Entity::new(dimension, entity_id, entity_ptr) + Entity::new(world, entity_id, entity_ptr) } /// Returns the entity associated to the player. - pub fn entity(&self) -> Entity> { + pub fn entity(&self) -> Entity> { let entity_id = { let player_lock = self.player.read(); player_lock.entity_id }; - let dimension = self.dimension.read(); + let world = self.world.read(); - let entity_data = dimension + let entity_data = world .entity_storage .get_by_id(entity_id) - .expect("Player entity should be in the given dimension"); + .expect("Player entity should be in the given world"); let entity_ptr = unsafe { entity_data.as_const_ptr() }; - Entity::new(dimension, entity_id, entity_ptr) + Entity::new(world, entity_id, entity_ptr) } /// Returns whether we have a received the login packet yet. pub fn logged_in(&self) -> bool { - let dimension = self.dimension.read(); + let world = self.world.read(); let player = self.player.write(); - player.entity(&dimension).is_some() + player.entity(&world).is_some() } /// Tell the server we changed our game options (i.e. render distance, main hand). diff --git a/azalea-client/src/movement.rs b/azalea-client/src/movement.rs index 145513c0..d33b4b4a 100755 --- a/azalea-client/src/movement.rs +++ b/azalea-client/src/movement.rs @@ -154,19 +154,19 @@ impl Client { // Set our current position to the provided Vec3, potentially clipping through blocks. pub async fn set_pos(&mut self, new_pos: Vec3) -> Result<(), MovePlayerError> { let player_lock = self.player.write(); - let mut dimension_lock = self.dimension.write(); + let mut world_lock = self.world.write(); - dimension_lock.set_entity_pos(player_lock.entity_id, new_pos)?; + world_lock.set_entity_pos(player_lock.entity_id, new_pos)?; Ok(()) } pub async fn move_entity(&mut self, movement: &Vec3) -> Result<(), MovePlayerError> { - let mut dimension_lock = self.dimension.write(); + let mut world_lock = self.world.write(); let player = self.player.write(); let mut entity = player - .entity_mut(&mut dimension_lock) + .entity_mut(&mut world_lock) .ok_or(MovePlayerError::PlayerNotInWorld)?; log::trace!( "move entity bounding box: {} {:?}", diff --git a/azalea-client/src/player.rs b/azalea-client/src/player.rs index ea6125ad..a355831b 100755 --- a/azalea-client/src/player.rs +++ b/azalea-client/src/player.rs @@ -1,13 +1,13 @@ use azalea_world::entity::Entity; -use azalea_world::Dimension; +use azalea_world::World; use uuid::Uuid; -/// Something that has a dimension associated to it. Usually, this is a `Client`. -pub trait DimensionHaver { - fn dimension(&self) -> &Dimension; +/// Something that has a world associated to it. Usually, this is a `Client`. +pub trait WorldHaver { + fn world(&self) -> &World; } -/// A player in the dimension or tab list. +/// A player in the world or tab list. #[derive(Default, Debug)] pub struct Player { /// The player's uuid. @@ -18,13 +18,13 @@ pub struct Player { impl Player { /// Get a reference to the entity of the player in the world. - pub fn entity<'d>(&'d self, dimension: &'d Dimension) -> Option> { - dimension.entity(self.entity_id) + pub fn entity<'d>(&'d self, world: &'d World) -> Option> { + world.entity(self.entity_id) } /// Get a mutable reference to the entity of the player in the world. - pub fn entity_mut<'d>(&'d self, dimension: &'d mut Dimension) -> Option { - dimension.entity_mut(self.entity_id) + pub fn entity_mut<'d>(&'d self, world: &'d mut World) -> Option { + world.entity_mut(self.entity_id) } pub fn set_uuid(&mut self, uuid: Uuid) { diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index 61368b28..6c18d147 100755 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -197,12 +197,12 @@ impl Add for ChunkSectionPos { } } -/// A block pos with an attached dimension +/// A block pos with an attached world #[derive(Debug, Clone)] pub struct GlobalPos { pub pos: BlockPos, // this is actually a ResourceKey in Minecraft, but i don't think it matters? - pub dimension: ResourceLocation, + pub world: ResourceLocation, } impl From<&BlockPos> for ChunkPos { @@ -297,7 +297,7 @@ impl McBufReadable for BlockPos { impl McBufReadable for GlobalPos { fn read_from(buf: &mut Cursor<&[u8]>) -> Result { Ok(GlobalPos { - dimension: ResourceLocation::read_from(buf)?, + world: ResourceLocation::read_from(buf)?, pos: BlockPos::read_from(buf)?, }) } @@ -326,7 +326,7 @@ impl McBufWritable for BlockPos { impl McBufWritable for GlobalPos { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - ResourceLocation::write_into(&self.dimension, buf)?; + ResourceLocation::write_into(&self.world, buf)?; BlockPos::write_into(&self.pos, buf)?; Ok(()) diff --git a/azalea-physics/src/collision/dimension_collisions.rs b/azalea-physics/src/collision/dimension_collisions.rs deleted file mode 100755 index fd4e5141..00000000 --- a/azalea-physics/src/collision/dimension_collisions.rs +++ /dev/null @@ -1,139 +0,0 @@ -use crate::collision::{BlockWithShape, VoxelShape, AABB}; -use azalea_block::BlockState; -use azalea_core::{ChunkPos, ChunkSectionPos, Cursor3d, CursorIterationType, EPSILON}; -use azalea_world::entity::EntityData; -use azalea_world::{Chunk, Dimension}; -use parking_lot::Mutex; -use std::sync::Arc; - -use super::Shapes; - -pub trait CollisionGetter { - fn get_block_collisions<'a>( - &'a self, - entity: Option<&EntityData>, - aabb: AABB, - ) -> BlockCollisions<'a>; -} - -impl CollisionGetter for Dimension { - fn get_block_collisions<'a>( - &'a self, - entity: Option<&EntityData>, - aabb: AABB, - ) -> BlockCollisions<'a> { - BlockCollisions::new(self, entity, aabb) - } -} - -pub struct BlockCollisions<'a> { - pub dimension: &'a Dimension, - // context: CollisionContext, - pub aabb: AABB, - pub entity_shape: VoxelShape, - pub cursor: Cursor3d, - pub only_suffocating_blocks: bool, -} - -impl<'a> BlockCollisions<'a> { - // TODO: the entity is stored in the context - pub fn new(dimension: &'a Dimension, _entity: Option<&EntityData>, aabb: AABB) -> Self { - let origin_x = (aabb.min_x - EPSILON) as i32 - 1; - let origin_y = (aabb.min_y - EPSILON) as i32 - 1; - let origin_z = (aabb.min_z - EPSILON) as i32 - 1; - - let end_x = (aabb.max_x + EPSILON) as i32 + 1; - let end_y = (aabb.max_y + EPSILON) as i32 + 1; - let end_z = (aabb.max_z + EPSILON) as i32 + 1; - - let cursor = Cursor3d::new(origin_x, origin_y, origin_z, end_x, end_y, end_z); - - Self { - dimension, - aabb, - entity_shape: VoxelShape::from(aabb), - cursor, - only_suffocating_blocks: false, - } - } - - fn get_chunk(&self, block_x: i32, block_z: i32) -> Option<&Arc>> { - let chunk_x = ChunkSectionPos::block_to_section_coord(block_x); - let chunk_z = ChunkSectionPos::block_to_section_coord(block_z); - let chunk_pos = ChunkPos::new(chunk_x, chunk_z); - - // TODO: minecraft caches chunk here - // int chunkX = SectionPos.blockToSectionCoord(blockX); - // int chunkZ = SectionPos.blockToSectionCoord(blockZ); - // long chunkPosLong = ChunkPos.asLong(chunkX, chunkZ); - // if (this.cachedBlockGetter != null && this.cachedBlockGetterPos == var5) { - // return this.cachedBlockGetter; - // } else { - // BlockGetter var7 = this.collisionGetter.getChunkForCollisions(chunkX, chunkZ); - // this.cachedBlockGetter = var7; - // this.cachedBlockGetterPos = chunkPosLong; - // return var7; - // } - - self.dimension[&chunk_pos].as_ref() - } -} - -impl<'a> Iterator for BlockCollisions<'a> { - type Item = VoxelShape; - - fn next(&mut self) -> Option { - while let Some(item) = self.cursor.next() { - if item.iteration_type == CursorIterationType::Corner { - continue; - } - - let chunk = self.get_chunk(item.pos.x, item.pos.z); - let chunk = match chunk { - Some(chunk) => chunk, - None => continue, - }; - - let pos = item.pos; - let block_state: BlockState = chunk - .lock() - .get(&(&pos).into(), self.dimension.min_y()) - .unwrap_or(BlockState::Air); - - // TODO: continue if self.only_suffocating_blocks and the block is not suffocating - - let block_shape = block_state.shape(); - - // if it's a full block do a faster collision check - if block_shape == &crate::collision::block_shape() { - 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 = - 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 - } -} diff --git a/azalea-physics/src/collision/mod.rs b/azalea-physics/src/collision/mod.rs index d5502f3d..aa585aa8 100755 --- a/azalea-physics/src/collision/mod.rs +++ b/azalea-physics/src/collision/mod.rs @@ -1,18 +1,18 @@ mod blocks; -mod dimension_collisions; mod discrete_voxel_shape; mod mergers; mod shape; +mod world_collisions; use std::ops::DerefMut; use azalea_core::{Axis, Vec3, AABB, EPSILON}; use azalea_world::entity::{Entity, EntityData}; -use azalea_world::{Dimension, MoveEntityError}; +use azalea_world::{MoveEntityError, World}; pub use blocks::BlockWithShape; -use dimension_collisions::CollisionGetter; pub use discrete_voxel_shape::*; pub use shape::*; +use world_collisions::CollisionGetter; pub enum MoverType { Own, @@ -34,7 +34,7 @@ pub trait MovableEntity { ) -> Result<(), MoveEntityError>; } -impl HasCollision for Dimension { +impl HasCollision for World { // private Vec3 collide(Vec3 var1) { // AABB var2 = this.getBoundingBox(); // List var3 = this.level.getEntityCollisions(this, var2.expandTowards(var1)); @@ -63,7 +63,7 @@ impl HasCollision for Dimension { fn collide(&self, movement: &Vec3, entity: &EntityData) -> Vec3 { let entity_bounding_box = entity.bounding_box; // TODO: get_entity_collisions - // let entity_collisions = dimension.get_entity_collisions(self, entity_bounding_box.expand_towards(movement)); + // let entity_collisions = world.get_entity_collisions(self, entity_bounding_box.expand_towards(movement)); let entity_collisions = Vec::new(); if movement.length_sqr() == 0.0 { *movement @@ -83,7 +83,7 @@ impl HasCollision for Dimension { } } -impl> MovableEntity for Entity<'_, D> { +impl> MovableEntity for Entity<'_, D> { /// Move an entity by a given delta, checking for collisions. fn move_colliding( &mut self, @@ -111,7 +111,7 @@ impl> MovableEntity for Entity<'_, D> { // movement = this.maybeBackOffFromEdge(movement, moverType); - let collide_result = { self.dimension.collide(movement, self) }; + let collide_result = { self.world.collide(movement, self) }; let move_distance = collide_result.length_sqr(); @@ -127,7 +127,7 @@ impl> MovableEntity for Entity<'_, D> { } }; - self.dimension.set_entity_pos(self.id, new_pos)?; + self.world.set_entity_pos(self.id, new_pos)?; } let x_collision = movement.x != collide_result.x; @@ -141,7 +141,7 @@ impl> MovableEntity for Entity<'_, D> { let _block_pos_below = self.on_pos_legacy(); // let _block_state_below = self - // .dimension + // .world // .get_block_state(&block_pos_below) // .expect("Couldn't get block state below"); @@ -198,7 +198,7 @@ fn collide_bounding_box( entity: Option<&EntityData>, movement: &Vec3, entity_bounding_box: &AABB, - dimension: &Dimension, + world: &World, entity_collisions: Vec, ) -> Vec3 { let mut collision_boxes: Vec = Vec::with_capacity(entity_collisions.len() + 1); @@ -210,7 +210,7 @@ fn collide_bounding_box( // TODO: world border let block_collisions = - dimension.get_block_collisions(entity, entity_bounding_box.expand_towards(movement)); + world.get_block_collisions(entity, entity_bounding_box.expand_towards(movement)); let block_collisions = block_collisions.collect::>(); collision_boxes.extend(block_collisions); collide_with_shapes(movement, *entity_bounding_box, &collision_boxes) diff --git a/azalea-physics/src/collision/world_collisions.rs b/azalea-physics/src/collision/world_collisions.rs new file mode 100644 index 00000000..65f7f5bb --- /dev/null +++ b/azalea-physics/src/collision/world_collisions.rs @@ -0,0 +1,139 @@ +use crate::collision::{BlockWithShape, VoxelShape, AABB}; +use azalea_block::BlockState; +use azalea_core::{ChunkPos, ChunkSectionPos, Cursor3d, CursorIterationType, EPSILON}; +use azalea_world::entity::EntityData; +use azalea_world::{Chunk, World}; +use parking_lot::Mutex; +use std::sync::Arc; + +use super::Shapes; + +pub trait CollisionGetter { + fn get_block_collisions<'a>( + &'a self, + entity: Option<&EntityData>, + aabb: AABB, + ) -> BlockCollisions<'a>; +} + +impl CollisionGetter for World { + fn get_block_collisions<'a>( + &'a self, + entity: Option<&EntityData>, + aabb: AABB, + ) -> BlockCollisions<'a> { + BlockCollisions::new(self, entity, aabb) + } +} + +pub struct BlockCollisions<'a> { + pub world: &'a World, + // context: CollisionContext, + pub aabb: AABB, + pub entity_shape: VoxelShape, + pub cursor: Cursor3d, + pub only_suffocating_blocks: bool, +} + +impl<'a> BlockCollisions<'a> { + // TODO: the entity is stored in the context + pub fn new(world: &'a World, _entity: Option<&EntityData>, aabb: AABB) -> Self { + let origin_x = (aabb.min_x - EPSILON) as i32 - 1; + let origin_y = (aabb.min_y - EPSILON) as i32 - 1; + let origin_z = (aabb.min_z - EPSILON) as i32 - 1; + + let end_x = (aabb.max_x + EPSILON) as i32 + 1; + let end_y = (aabb.max_y + EPSILON) as i32 + 1; + let end_z = (aabb.max_z + EPSILON) as i32 + 1; + + let cursor = Cursor3d::new(origin_x, origin_y, origin_z, end_x, end_y, end_z); + + Self { + world, + aabb, + entity_shape: VoxelShape::from(aabb), + cursor, + only_suffocating_blocks: false, + } + } + + fn get_chunk(&self, block_x: i32, block_z: i32) -> Option<&Arc>> { + let chunk_x = ChunkSectionPos::block_to_section_coord(block_x); + let chunk_z = ChunkSectionPos::block_to_section_coord(block_z); + let chunk_pos = ChunkPos::new(chunk_x, chunk_z); + + // TODO: minecraft caches chunk here + // int chunkX = SectionPos.blockToSectionCoord(blockX); + // int chunkZ = SectionPos.blockToSectionCoord(blockZ); + // long chunkPosLong = ChunkPos.asLong(chunkX, chunkZ); + // if (this.cachedBlockGetter != null && this.cachedBlockGetterPos == var5) { + // return this.cachedBlockGetter; + // } else { + // BlockGetter var7 = this.collisionGetter.getChunkForCollisions(chunkX, chunkZ); + // this.cachedBlockGetter = var7; + // this.cachedBlockGetterPos = chunkPosLong; + // return var7; + // } + + self.world[&chunk_pos].as_ref() + } +} + +impl<'a> Iterator for BlockCollisions<'a> { + type Item = VoxelShape; + + fn next(&mut self) -> Option { + while let Some(item) = self.cursor.next() { + if item.iteration_type == CursorIterationType::Corner { + continue; + } + + let chunk = self.get_chunk(item.pos.x, item.pos.z); + let chunk = match chunk { + Some(chunk) => chunk, + None => continue, + }; + + let pos = item.pos; + let block_state: BlockState = chunk + .lock() + .get(&(&pos).into(), self.world.min_y()) + .unwrap_or(BlockState::Air); + + // TODO: continue if self.only_suffocating_blocks and the block is not suffocating + + let block_shape = block_state.shape(); + + // if it's a full block do a faster collision check + if block_shape == &crate::collision::block_shape() { + 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 = + 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 + } +} diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 852874b8..2295e6f2 100755 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -8,7 +8,7 @@ use azalea_block::{Block, BlockState}; use azalea_core::{BlockPos, Vec3}; use azalea_world::{ entity::{Entity, EntityData}, - Dimension, + World, }; use collision::{MovableEntity, MoverType}; @@ -19,7 +19,7 @@ pub trait HasPhysics { fn jump_from_ground(&mut self); } -impl> HasPhysics for Entity<'_, D> { +impl> HasPhysics for Entity<'_, D> { /// Move the entity with the given acceleration while handling friction, /// gravity, collisions, and some other stuff. fn travel(&mut self, acceleration: &Vec3) { @@ -40,7 +40,7 @@ impl> HasPhysics for Entity<'_, D> { let block_pos_below = get_block_pos_below_that_affects_movement(self); let block_state_below = self - .dimension + .world .get_block_state(&block_pos_below) .unwrap_or(BlockState::Air); let block_below: Box = block_state_below.into(); @@ -142,7 +142,7 @@ fn get_block_pos_below_that_affects_movement(entity: &EntityData) -> BlockPos { ) } -fn handle_relative_friction_and_calculate_movement>( +fn handle_relative_friction_and_calculate_movement>( entity: &mut Entity, acceleration: &Vec3, block_friction: f32, @@ -181,10 +181,10 @@ fn get_friction_influenced_speed(entity: &EntityData, friction: f32) -> f32 { /// Returns the what the entity's jump should be multiplied by based on the /// block they're standing on. -fn block_jump_factor>(entity: &Entity) -> f32 { - let block_at_pos = entity.dimension.get_block_state(&entity.pos().into()); +fn block_jump_factor>(entity: &Entity) -> f32 { + let block_at_pos = entity.world.get_block_state(&entity.pos().into()); let block_below = entity - .dimension + .world .get_block_state(&get_block_pos_below_that_affects_movement(entity)); let block_at_pos_jump_factor = if let Some(block) = block_at_pos { @@ -209,11 +209,11 @@ fn block_jump_factor>(entity: &Entity) -> f32 // public double getJumpBoostPower() { // return this.hasEffect(MobEffects.JUMP) ? (double)(0.1F * (float)(this.getEffect(MobEffects.JUMP).getAmplifier() + 1)) : 0.0D; // } -fn jump_power>(entity: &Entity) -> f32 { +fn jump_power>(entity: &Entity) -> f32 { 0.42 * block_jump_factor(entity) } -fn jump_boost_power>(_entity: &Entity) -> f64 { +fn jump_boost_power>(_entity: &Entity) -> f64 { // TODO: potion effects // if let Some(effects) = entity.effects() { // if let Some(jump_effect) = effects.get(&Effect::Jump) { @@ -231,14 +231,14 @@ fn jump_boost_power>(_entity: &Entity) -> f64 mod tests { use super::*; use azalea_core::ChunkPos; - use azalea_world::{Chunk, Dimension}; + use azalea_world::{Chunk, World}; use uuid::Uuid; #[test] fn test_gravity() { - let mut dim = Dimension::default(); + let mut world = World::default(); - dim.add_entity( + world.add_entity( 0, EntityData::new( Uuid::from_u128(0), @@ -249,7 +249,7 @@ mod tests { }, ), ); - let mut entity = dim.entity_mut(0).unwrap(); + let mut entity = world.entity_mut(0).unwrap(); // y should start at 70 assert_eq!(entity.pos().y, 70.); entity.ai_step(); @@ -266,10 +266,11 @@ mod tests { } #[test] fn test_collision() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.add_entity( + world.add_entity( 0, EntityData::new( Uuid::from_u128(0), @@ -280,12 +281,12 @@ mod tests { }, ), ); - let block_state = dim.set_block_state(&BlockPos { x: 0, y: 69, z: 0 }, BlockState::Stone); + let block_state = world.set_block_state(&BlockPos { x: 0, y: 69, z: 0 }, BlockState::Stone); assert!( block_state.is_some(), "Block state should exist, if this fails that means the chunk wasn't loaded and the block didn't get placed" ); - let mut entity = dim.entity_mut(0).unwrap(); + let mut entity = world.entity_mut(0).unwrap(); entity.ai_step(); // delta will change, but it won't move until next tick assert_eq!(entity.pos().y, 70.); @@ -297,10 +298,11 @@ mod tests { #[test] fn test_slab_collision() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.add_entity( + world.add_entity( 0, EntityData::new( Uuid::from_u128(0), @@ -311,7 +313,7 @@ mod tests { }, ), ); - let block_state = dim.set_block_state( + let block_state = world.set_block_state( &BlockPos { x: 0, y: 69, z: 0 }, BlockState::StoneSlab_BottomFalse, ); @@ -319,7 +321,7 @@ mod tests { block_state.is_some(), "Block state should exist, if this fails that means the chunk wasn't loaded and the block didn't get placed" ); - let mut entity = dim.entity_mut(0).unwrap(); + let mut entity = world.entity_mut(0).unwrap(); // do a few steps so we fall on the slab for _ in 0..20 { entity.ai_step(); @@ -329,10 +331,11 @@ mod tests { #[test] fn test_top_slab_collision() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.add_entity( + world.add_entity( 0, EntityData::new( Uuid::from_u128(0), @@ -343,7 +346,7 @@ mod tests { }, ), ); - let block_state = dim.set_block_state( + let block_state = world.set_block_state( &BlockPos { x: 0, y: 69, z: 0 }, BlockState::StoneSlab_TopFalse, ); @@ -351,7 +354,7 @@ mod tests { block_state.is_some(), "Block state should exist, if this fails that means the chunk wasn't loaded and the block didn't get placed" ); - let mut entity = dim.entity_mut(0).unwrap(); + let mut entity = world.entity_mut(0).unwrap(); // do a few steps so we fall on the slab for _ in 0..20 { entity.ai_step(); @@ -361,10 +364,11 @@ mod tests { #[test] fn test_weird_wall_collision() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.add_entity( + world.add_entity( 0, EntityData::new( Uuid::from_u128(0), @@ -375,7 +379,7 @@ mod tests { }, ), ); - let block_state = dim.set_block_state( + let block_state = world.set_block_state( &BlockPos { x: 0, y: 69, z: 0 }, BlockState::CobblestoneWall_LowLowLowFalseFalseLow, ); @@ -383,7 +387,7 @@ mod tests { block_state.is_some(), "Block state should exist, if this fails that means the chunk wasn't loaded and the block didn't get placed" ); - let mut entity = dim.entity_mut(0).unwrap(); + let mut entity = world.entity_mut(0).unwrap(); // do a few steps so we fall on the slab for _ in 0..20 { entity.ai_step(); diff --git a/azalea-world/src/chunk_storage.rs b/azalea-world/src/chunk_storage.rs index 85f0ebb3..a03cbe7b 100755 --- a/azalea-world/src/chunk_storage.rs +++ b/azalea-world/src/chunk_storage.rs @@ -1,6 +1,6 @@ use crate::palette::PalettedContainer; use crate::palette::PalettedContainerType; -use crate::Dimension; +use crate::World; use azalea_block::BlockState; use azalea_buf::BufReadError; use azalea_buf::{McBufReadable, McBufWritable}; @@ -143,7 +143,7 @@ impl IndexMut<&ChunkPos> for ChunkStorage { impl Chunk { pub fn read_with_dimension( buf: &mut Cursor<&[u8]>, - data: &Dimension, + data: &World, ) -> Result { Self::read_with_dimension_height(buf, data.height()) } diff --git a/azalea-world/src/entity/mod.rs b/azalea-world/src/entity/mod.rs index 540bfeed..4611f215 100644 --- a/azalea-world/src/entity/mod.rs +++ b/azalea-world/src/entity/mod.rs @@ -5,7 +5,7 @@ pub mod metadata; use self::attributes::{AttributeInstance, AttributeModifiers}; pub use self::metadata::EntityMetadata; -use crate::Dimension; +use crate::World; use azalea_block::BlockState; use azalea_core::{BlockPos, Vec3, AABB}; pub use data::*; @@ -15,22 +15,22 @@ use std::ops::{Deref, DerefMut}; use std::ptr::NonNull; use uuid::Uuid; -/// A reference to an entity in a dimension. +/// A reference to an entity in a world. #[derive(Debug)] -pub struct Entity<'d, D = &'d mut Dimension> { - /// The dimension this entity is in. - pub dimension: D, +pub struct Entity<'d, D = &'d mut World> { + /// The world this entity is in. + pub world: D, /// The incrementing numerical id of the entity. pub id: u32, pub data: NonNull, _marker: PhantomData<&'d ()>, } -impl<'d, D: Deref> Entity<'d, D> { - pub fn new(dimension: D, id: u32, data: NonNull) -> Self { +impl<'d, D: Deref> Entity<'d, D> { + pub fn new(world: D, id: u32, data: NonNull) -> Self { // TODO: have this be based on the entity type Self { - dimension, + world, id, data, _marker: PhantomData, @@ -38,12 +38,12 @@ impl<'d, D: Deref> Entity<'d, D> { } } -impl<'d, D: DerefMut> Entity<'d, D> { +impl<'d, D: DerefMut> Entity<'d, D> { /// Sets the position of the entity. This doesn't update the cache in /// azalea-world, and should only be used within azalea-world! /// /// # Safety - /// Cached position in the dimension must be updated. + /// Cached position in the world must be updated. pub unsafe fn move_unchecked(&mut self, new_pos: Vec3) { self.pos = new_pos; let bounding_box = self.make_bounding_box(); @@ -94,7 +94,7 @@ impl<'d, D: DerefMut> Entity<'d, D> { } } -impl<'d, D: Deref> Entity<'d, D> { +impl<'d, D: Deref> Entity<'d, D> { #[inline] pub fn pos(&self) -> &Vec3 { &self.pos @@ -129,10 +129,10 @@ impl<'d, D: Deref> Entity<'d, D> { // TODO: check if block below is a fence, wall, or fence gate let block_pos = pos.down(1); - let block_state = self.dimension.get_block_state(&block_pos); + let block_state = self.world.get_block_state(&block_pos); if block_state == Some(BlockState::Air) { let block_pos_below = block_pos.down(1); - let block_state_below = self.dimension.get_block_state(&block_pos_below); + let block_state_below = self.world.get_block_state(&block_pos_below); if let Some(_block_state_below) = block_state_below { // if block_state_below.is_fence() // || block_state_below.is_wall() @@ -149,13 +149,13 @@ impl<'d, D: Deref> Entity<'d, D> { // impl< // 'd, -// D: DerefMut + Deref, -// D2: Deref, +// D: DerefMut + Deref, +// D2: Deref, // > From> for Entity<'d, D2> // { // fn from(entity: Entity<'d, D>) -> Entity<'d, D> { // Entity { -// dimension: entity.dimension, +// world: entity.world, // id: entity.id, // data: entity.data, // _marker: PhantomData, @@ -163,13 +163,13 @@ impl<'d, D: Deref> Entity<'d, D> { // } // } -impl> DerefMut for Entity<'_, D> { +impl> DerefMut for Entity<'_, D> { fn deref_mut(&mut self) -> &mut Self::Target { unsafe { self.data.as_mut() } } } -impl> Deref for Entity<'_, D> { +impl> Deref for Entity<'_, D> { type Target = EntityData; fn deref(&self) -> &Self::Target { @@ -181,7 +181,7 @@ impl> Deref for Entity<'_, D> { pub struct EntityData { pub uuid: Uuid, /// The position of the entity right now. - /// This can be changde with unsafe_move, but the correct way is with dimension.move_entity + /// This can be changde with unsafe_move, but the correct way is with world.move_entity pos: Vec3, /// The position of the entity last tick. pub last_pos: Vec3, @@ -264,7 +264,7 @@ impl EntityData { } } - /// Get the position of the entity in the dimension. + /// Get the position of the entity in the world. #[inline] pub fn pos(&self) -> &Vec3 { &self.pos @@ -295,9 +295,9 @@ mod tests { #[test] fn from_mut_entity_to_ref_entity() { - let mut dim = Dimension::default(); + let mut world = World::default(); let uuid = Uuid::from_u128(100); - dim.add_entity( + world.add_entity( 0, EntityData::new( uuid, @@ -305,7 +305,7 @@ mod tests { EntityMetadata::Player(metadata::Player::default()), ), ); - let entity: Entity = dim.entity_mut(0).unwrap(); + let entity: Entity = world.entity_mut(0).unwrap(); let entity_ref = Entity::from(entity); assert_eq!(entity_ref.uuid, uuid); } diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 30e09fe9..a802f4c3 100755 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -22,10 +22,9 @@ use std::{ use thiserror::Error; use uuid::Uuid; -/// A dimension is a collection of chunks and entities. -/// Minecraft calls these "Levels", Fabric calls them "Worlds", Minestom calls them "Instances". +/// A world is a collection of chunks and entities. They're called "levels" in Minecraft's source code. #[derive(Debug, Default)] -pub struct Dimension { +pub struct World { pub chunk_storage: ChunkStorage, pub entity_storage: EntityStorage, } @@ -36,9 +35,9 @@ pub enum MoveEntityError { EntityDoesNotExist, } -impl Dimension { +impl World { pub fn new(chunk_radius: u32, height: u32, min_y: i32) -> Self { - Dimension { + World { chunk_storage: ChunkStorage::new(chunk_radius, height, min_y), entity_storage: EntityStorage::new(), } @@ -127,13 +126,13 @@ impl Dimension { self.entity_storage.get_mut_by_id(id) } - pub fn entity(&self, id: u32) -> Option> { + pub fn entity(&self, id: u32) -> Option> { let entity_data = self.entity_storage.get_by_id(id)?; let entity_ptr = unsafe { entity_data.as_const_ptr() }; Some(Entity::new(self, id, entity_ptr)) } - pub fn entity_mut(&mut self, id: u32) -> Option> { + pub fn entity_mut(&mut self, id: u32) -> Option> { let entity_data = self.entity_storage.get_mut_by_id(id)?; let entity_ptr = unsafe { entity_data.as_ptr() }; Some(Entity::new(self, id, entity_ptr)) @@ -157,14 +156,14 @@ impl Dimension { } } -impl Index<&ChunkPos> for Dimension { +impl Index<&ChunkPos> for World { type Output = Option>>; fn index(&self, pos: &ChunkPos) -> &Self::Output { &self.chunk_storage[pos] } } -impl IndexMut<&ChunkPos> for Dimension { +impl IndexMut<&ChunkPos> for World { fn index_mut<'a>(&'a mut self, pos: &ChunkPos) -> &'a mut Self::Output { &mut self.chunk_storage[pos] } diff --git a/azalea/examples/potatobot/main.rs b/azalea/examples/potatobot/main.rs index 66ddfcc0..e585c41d 100755 --- a/azalea/examples/potatobot/main.rs +++ b/azalea/examples/potatobot/main.rs @@ -49,7 +49,7 @@ async fn deposit(bot: &mut Client, state: State) -> anyhow::Result<()> { bot.goto(Vec3::new(0, 70, 0)).await?; let chest = bot - .open_container(&bot.dimension.block_at(BlockPos::new(0, 70, 0))) + .open_container(&bot.world.block_at(BlockPos::new(0, 70, 0))) .await .unwrap(); diff --git a/azalea/examples/pvp.rs b/azalea/examples/pvp.rs index 435c335c..87d83c6d 100755 --- a/azalea/examples/pvp.rs +++ b/azalea/examples/pvp.rs @@ -36,10 +36,7 @@ async fn swarm_handle(swarm: Swarm, event: Event, state: State) { match event { Event::Tick => { // choose an arbitrary player within render distance to target - if let Some(target) = swarm - .dimension - .find_one_entity(|e| e.id == "minecraft:player") - { + if let Some(target) = swarm.world.find_one_entity(|e| e.id == "minecraft:player") { for bot in swarm { bot.tick_goto_goal(pathfinder::Goals::Reach(target.bounding_box)); // if target.bounding_box.distance(bot.eyes) < bot.reach_distance() { diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs index 9fd9fe90..6f31512e 100644 --- a/azalea/src/pathfinder/mod.rs +++ b/azalea/src/pathfinder/mod.rs @@ -74,11 +74,11 @@ impl Trait for azalea_client::Client { let successors = |node: &Node| { let mut edges = Vec::new(); - let dimension = self.dimension.read(); + let world = self.world.read(); for possible_move in possible_moves.iter() { edges.push(Edge { target: possible_move.next_node(node), - cost: possible_move.cost(&dimension, node), + cost: possible_move.cost(&world, node), }); } edges diff --git a/azalea/src/pathfinder/moves.rs b/azalea/src/pathfinder/moves.rs index a08d4b80..63e24412 100644 --- a/azalea/src/pathfinder/moves.rs +++ b/azalea/src/pathfinder/moves.rs @@ -1,11 +1,11 @@ use super::{Node, VerticalVel}; use azalea_core::{BlockPos, CardinalDirection}; use azalea_physics::collision::{self, BlockWithShape}; -use azalea_world::Dimension; +use azalea_world::World; /// whether this block is passable -fn is_block_passable(pos: &BlockPos, dim: &Dimension) -> bool { - if let Some(block) = dim.get_block_state(pos) { +fn is_block_passable(pos: &BlockPos, world: &World) -> bool { + if let Some(block) = world.get_block_state(pos) { block.shape() == &collision::empty_shape() } else { false @@ -13,8 +13,8 @@ fn is_block_passable(pos: &BlockPos, dim: &Dimension) -> bool { } /// whether this block has a solid hitbox (i.e. we can stand on it) -fn is_block_solid(pos: &BlockPos, dim: &Dimension) -> bool { - if let Some(block) = dim.get_block_state(pos) { +fn is_block_solid(pos: &BlockPos, world: &World) -> bool { + if let Some(block) = world.get_block_state(pos) { block.shape() == &collision::block_shape() } else { false @@ -22,21 +22,22 @@ fn is_block_solid(pos: &BlockPos, dim: &Dimension) -> bool { } /// Whether this block and the block above are passable -fn is_passable(pos: &BlockPos, dim: &Dimension) -> bool { - is_block_passable(pos, dim) && is_block_passable(&pos.up(1), dim) +fn is_passable(pos: &BlockPos, world: &World) -> bool { + is_block_passable(pos, world) && is_block_passable(&pos.up(1), world) } /// Whether we can stand in this position. Checks if the block below is solid, /// and that the two blocks above that are passable. -fn is_standable(pos: &BlockPos, dim: &Dimension) -> bool { - is_block_solid(&pos.down(1), dim) && is_passable(pos, dim) + +fn is_standable(pos: &BlockPos, world: &World) -> bool { + is_block_solid(&pos.down(1), world) && is_passable(pos, world) } const JUMP_COST: f32 = 0.5; const WALK_ONE_BLOCK_COST: f32 = 1.0; pub trait Move { - fn cost(&self, dim: &Dimension, node: &Node) -> f32; + fn cost(&self, world: &World, node: &Node) -> f32; /// 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 { @@ -49,8 +50,9 @@ pub trait Move { pub struct ForwardMove(pub CardinalDirection); impl Move for ForwardMove { - fn cost(&self, dim: &Dimension, node: &Node) -> f32 { - if is_standable(&(node.pos + self.offset()), dim) && node.vertical_vel == VerticalVel::None + fn cost(&self, world: &World, node: &Node) -> f32 { + if is_standable(&(node.pos + self.offset()), world) + && node.vertical_vel == VerticalVel::None { WALK_ONE_BLOCK_COST } else { @@ -64,10 +66,10 @@ impl Move for ForwardMove { pub struct AscendMove(pub CardinalDirection); impl Move for AscendMove { - fn cost(&self, dim: &Dimension, node: &Node) -> f32 { + fn cost(&self, world: &World, node: &Node) -> f32 { if node.vertical_vel == VerticalVel::None - && is_block_passable(&node.pos.up(2), dim) - && is_standable(&(node.pos + self.offset()), dim) + && is_block_passable(&node.pos.up(2), world) + && is_standable(&(node.pos + self.offset()), world) { WALK_ONE_BLOCK_COST + JUMP_COST } else { @@ -86,11 +88,11 @@ impl Move for AscendMove { } pub struct DescendMove(pub CardinalDirection); impl Move for DescendMove { - fn cost(&self, dim: &Dimension, node: &Node) -> f32 { + fn cost(&self, world: &World, node: &Node) -> f32 { // check whether 3 blocks vertically forward are passable if node.vertical_vel == VerticalVel::None - && is_standable(&(node.pos + self.offset()), dim) - && is_block_passable(&(node.pos + self.offset().up(2)), dim) + && is_standable(&(node.pos + self.offset()), world) + && is_block_passable(&(node.pos + self.offset().up(2)), world) { WALK_ONE_BLOCK_COST } else { @@ -109,24 +111,24 @@ impl Move for DescendMove { } pub struct DiagonalMove(pub CardinalDirection); impl Move for DiagonalMove { - fn cost(&self, dim: &Dimension, node: &Node) -> f32 { + fn cost(&self, world: &World, node: &Node) -> f32 { if node.vertical_vel != VerticalVel::None { return f32::INFINITY; } if !is_passable( &BlockPos::new(node.pos.x + self.0.x(), node.pos.y, node.pos.z + self.0.z()), - dim, + world, ) && !is_passable( &BlockPos::new( node.pos.x + self.0.right().x(), node.pos.y, node.pos.z + self.0.right().z(), ), - dim, + world, ) { return f32::INFINITY; } - if !is_standable(&(node.pos + self.offset()), dim) { + if !is_standable(&(node.pos + self.offset()), world) { return f32::INFINITY; } WALK_ONE_BLOCK_COST * 1.4 @@ -152,40 +154,43 @@ mod tests { #[test] fn test_is_passable() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.set_block_state(&BlockPos::new(0, 0, 0), BlockState::Stone); - dim.set_block_state(&BlockPos::new(0, 1, 0), BlockState::Air); + world.set_block_state(&BlockPos::new(0, 0, 0), BlockState::Stone); + world.set_block_state(&BlockPos::new(0, 1, 0), BlockState::Air); - assert_eq!(is_block_passable(&BlockPos::new(0, 0, 0), &dim), false); - assert_eq!(is_block_passable(&BlockPos::new(0, 1, 0), &dim), true); + assert_eq!(is_block_passable(&BlockPos::new(0, 0, 0), &world), false); + assert_eq!(is_block_passable(&BlockPos::new(0, 1, 0), &world), true); } #[test] fn test_is_solid() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.set_block_state(&BlockPos::new(0, 0, 0), BlockState::Stone); - dim.set_block_state(&BlockPos::new(0, 1, 0), BlockState::Air); + world.set_block_state(&BlockPos::new(0, 0, 0), BlockState::Stone); + world.set_block_state(&BlockPos::new(0, 1, 0), BlockState::Air); - assert_eq!(is_block_solid(&BlockPos::new(0, 0, 0), &dim), true); - assert_eq!(is_block_solid(&BlockPos::new(0, 1, 0), &dim), false); + assert_eq!(is_block_solid(&BlockPos::new(0, 0, 0), &world), true); + assert_eq!(is_block_solid(&BlockPos::new(0, 1, 0), &world), false); } #[test] fn test_is_standable() { - let mut dim = Dimension::default(); - dim.set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) + let mut world = World::default(); + world + .set_chunk(&ChunkPos { x: 0, z: 0 }, Some(Chunk::default())) .unwrap(); - dim.set_block_state(&BlockPos::new(0, 0, 0), BlockState::Stone); - dim.set_block_state(&BlockPos::new(0, 1, 0), BlockState::Air); - dim.set_block_state(&BlockPos::new(0, 2, 0), BlockState::Air); - dim.set_block_state(&BlockPos::new(0, 3, 0), BlockState::Air); - - assert!(is_standable(&BlockPos::new(0, 1, 0), &dim)); - assert!(!is_standable(&BlockPos::new(0, 0, 0), &dim)); - assert!(!is_standable(&BlockPos::new(0, 2, 0), &dim)); + world.set_block_state(&BlockPos::new(0, 0, 0), BlockState::Stone); + world.set_block_state(&BlockPos::new(0, 1, 0), BlockState::Air); + world.set_block_state(&BlockPos::new(0, 2, 0), BlockState::Air); + world.set_block_state(&BlockPos::new(0, 3, 0), BlockState::Air); + + assert!(is_standable(&BlockPos::new(0, 1, 0), &world)); + assert!(!is_standable(&BlockPos::new(0, 0, 0), &world)); + assert!(!is_standable(&BlockPos::new(0, 2, 0), &world)); } } diff --git a/bot/src/main.rs b/bot/src/main.rs index ce627651..dd542a1c 100755 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -59,7 +59,7 @@ async fn handle(bot: Client, event: Event, _state: State) -> anyhow::Result<()> println!("{}", m.message().to_ansi(None)); if m.message().to_string() == " goto" { let target_pos_vec3 = *(bot - .dimension + .world .read() .entity_by_uuid(&uuid::uuid!("6536bfed869548fd83a1ecd24cf2a0fd")) .unwrap() -- cgit v1.2.3