From babb0d3a7442de547e6fa92463338e54733e4532 Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 11 Mar 2023 22:33:07 -0600 Subject: [PATCH] update_hit_result_component --- azalea-client/src/client.rs | 4 +- azalea-client/src/interact.rs | 48 +++++++++++++++---- azalea-client/src/packet_handling.rs | 8 ++-- azalea-physics/src/clip.rs | 24 +++++----- azalea-physics/src/lib.rs | 8 ++-- .../game/serverbound_use_item_on_packet.rs | 8 ++-- azalea-world/src/container.rs | 4 +- azalea-world/src/entity/info.rs | 8 ++-- azalea-world/src/world.rs | 16 +++---- azalea/examples/testbot.rs | 2 +- azalea/src/pathfinder/mod.rs | 4 +- azalea/src/swarm/mod.rs | 6 +-- 12 files changed, 86 insertions(+), 54 deletions(-) diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index f0778d8a..fa182ed8 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -444,8 +444,8 @@ impl Client { pub fn world(&self) -> Arc> { let world_name = self.component::(); let ecs = self.ecs.lock(); - let world_container = ecs.resource::(); - world_container.get(&world_name).unwrap() + let instance_container = ecs.resource::(); + instance_container.get(&world_name).unwrap() } /// Returns whether we have a received the login packet yet. diff --git a/azalea-client/src/interact.rs b/azalea-client/src/interact.rs index c49cc510..d9db5a37 100644 --- a/azalea-client/src/interact.rs +++ b/azalea-client/src/interact.rs @@ -1,15 +1,24 @@ -use azalea_core::{BlockPos, Direction, GameMode}; +use azalea_core::{BlockHitResult, BlockPos, Direction, GameMode, Vec3}; +use azalea_physics::clip::{BlockShapeType, ClipContext, FluidPickType}; use azalea_protocol::packets::game::{ serverbound_interact_packet::InteractionHand, - serverbound_use_item_on_packet::{BlockHitResult, ServerboundUseItemOnPacket}, + serverbound_use_item_on_packet::{BlockHit, ServerboundUseItemOnPacket}, +}; +use azalea_world::{ + entity::{view_vector, EyeHeight, LookDirection, Position, WorldName}, + InstanceContainer, }; -use azalea_world::entity::{view_vector, EyeHeight, LookDirection, Position}; use bevy_app::{App, Plugin}; -use bevy_ecs::{component::Component, entity::Entity, event::EventReader, system::Query}; +use bevy_ecs::{ + component::Component, + entity::Entity, + event::EventReader, + system::{Query, Res}, +}; use derive_more::{Deref, DerefMut}; use log::warn; -use crate::{local_player::LocalGameMode, Client, LocalPlayer, PlayerInfo}; +use crate::{local_player::LocalGameMode, Client, LocalPlayer}; /// A plugin that allows clients to interact with blocks in the world. pub struct InteractPlugin; @@ -73,7 +82,7 @@ fn handle_block_interact_event( local_player.write_packet( ServerboundUseItemOnPacket { hand: InteractionHand::MainHand, - block_hit: BlockHitResult { + block_hit: BlockHit { block_pos: event.position, direction: Direction::Up, location: event.position.center(), @@ -93,15 +102,38 @@ fn update_hit_result_component( &Position, &EyeHeight, &LookDirection, + &WorldName, )>, + instance_container: Res, ) { - for (hit_result, game_mode, position, eye_height, look_direction) in &mut query { + for (mut hit_result_ref, game_mode, position, eye_height, look_direction, world_name) in + &mut query + { let pick_range = if game_mode.current == GameMode::Creative { 6. } else { 4.5 }; let view_vector = view_vector(look_direction); - let end_position = **position + view_vector * pick_range; + let eye_position = Vec3 { + x: position.x, + y: position.y + **eye_height as f64, + z: position.z, + }; + let end_position = eye_position + view_vector * pick_range; + let instance_lock = instance_container + .get(world_name) + .expect("entities must always be in a valid world"); + let instance = instance_lock.read(); + let hit_result = azalea_physics::clip::clip( + &instance.chunks, + ClipContext { + from: eye_position, + to: end_position, + block_shape_type: BlockShapeType::Outline, + fluid_pick_type: FluidPickType::None, + }, + ); + **hit_result_ref = hit_result; } } diff --git a/azalea-client/src/packet_handling.rs b/azalea-client/src/packet_handling.rs index f0d49cd1..e7f8ff25 100644 --- a/azalea-client/src/packet_handling.rs +++ b/azalea-client/src/packet_handling.rs @@ -195,7 +195,7 @@ fn process_packet_events(ecs: &mut World) { )>, ResMut, )> = SystemState::new(ecs); - let (mut commands, mut query, mut world_container) = system_state.get_mut(ecs); + let (mut commands, mut query, mut instance_container) = system_state.get_mut(ecs); let (mut local_player, world_name, game_profile, client_information) = query.get_mut(player_entity).unwrap(); @@ -221,16 +221,16 @@ fn process_packet_events(ecs: &mut World) { .entity(player_entity) .insert(WorldName(new_world_name.clone())); } - // add this world to the world_container (or don't if it's already + // add this world to the instance_container (or don't if it's already // there) - let weak_world = world_container.insert( + let weak_world = instance_container.insert( new_world_name.clone(), dimension.height, dimension.min_y, ); // set the partial_world to an empty world // (when we add chunks or entities those will be in the - // world_container) + // instance_container) *local_player.partial_instance.write() = PartialInstance::new( client_information.view_distance.into(), diff --git a/azalea-physics/src/clip.rs b/azalea-physics/src/clip.rs index bde8c94d..60067ffe 100644 --- a/azalea-physics/src/clip.rs +++ b/azalea-physics/src/clip.rs @@ -10,9 +10,9 @@ use crate::collision::{BlockWithShape, VoxelShape}; pub struct ClipContext { pub from: Vec3, pub to: Vec3, - pub block: BlockShapeGetter, - pub fluid: CanPickFluid, - pub collision_context: EntityCollisionContext, + pub block_shape_type: BlockShapeType, + pub fluid_pick_type: FluidPickType, + // pub collision_context: EntityCollisionContext, } impl ClipContext { // minecraft passes in the world and blockpos here... but it doesn't actually @@ -20,24 +20,24 @@ impl ClipContext { pub fn block_shape(&self, block_state: BlockState) -> &VoxelShape { // TODO: implement the other shape getters // (see the ClipContext.Block class in the vanilla source) - match self.block { - BlockShapeGetter::Collider => block_state.shape(), - BlockShapeGetter::Outline => block_state.shape(), - BlockShapeGetter::Visual => block_state.shape(), - BlockShapeGetter::FallDamageResetting => block_state.shape(), + match self.block_shape_type { + BlockShapeType::Collider => block_state.shape(), + BlockShapeType::Outline => block_state.shape(), + BlockShapeType::Visual => block_state.shape(), + BlockShapeType::FallDamageResetting => block_state.shape(), } } } #[derive(Debug, Copy, Clone)] -pub enum BlockShapeGetter { +pub enum BlockShapeType { Collider, Outline, Visual, FallDamageResetting, } #[derive(Debug, Copy, Clone)] -pub enum CanPickFluid { +pub enum FluidPickType { None, SourceOnly, Any, @@ -52,7 +52,7 @@ pub struct EntityCollisionContext { pub entity: Entity, } -pub fn clip(chunk_storage: &mut ChunkStorage, context: ClipContext) -> BlockHitResult { +pub fn clip(chunk_storage: &ChunkStorage, context: ClipContext) -> BlockHitResult { traverse_blocks( context.from, context.to, @@ -108,7 +108,7 @@ fn clip_with_interaction_override( block_state: &BlockState, ) -> Option { let block_hit_result = block_shape.clip(from, to, block_pos); - if let Some(mut block_hit_result) = block_hit_result { + if let Some(block_hit_result) = block_hit_result { // TODO: minecraft calls .getInteractionShape here // are there even any blocks that have a physics shape different from the // interaction shape??? diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index d99e65ad..1a975680 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -54,10 +54,10 @@ fn travel( ), With, >, - world_container: Res, + instance_container: Res, ) { for (mut physics, direction, mut position, attributes, world_name) in &mut query { - let world_lock = world_container + let world_lock = instance_container .get(world_name) .expect("All entities should be in a valid world"); let world = world_lock.read(); @@ -176,14 +176,14 @@ pub fn force_jump_listener( &Sprinting, &WorldName, )>, - world_container: Res, + instance_container: Res, mut events: EventReader, ) { for event in events.iter() { if let Ok((mut physics, position, direction, sprinting, world_name)) = query.get_mut(event.0) { - let world_lock = world_container + let world_lock = instance_container .get(world_name) .expect("All entities should be in a valid world"); let world = world_lock.read(); diff --git a/azalea-protocol/src/packets/game/serverbound_use_item_on_packet.rs b/azalea-protocol/src/packets/game/serverbound_use_item_on_packet.rs index 66acd897..50cbe914 100755 --- a/azalea-protocol/src/packets/game/serverbound_use_item_on_packet.rs +++ b/azalea-protocol/src/packets/game/serverbound_use_item_on_packet.rs @@ -7,13 +7,13 @@ use std::io::{Cursor, Write}; #[derive(Clone, Debug, McBuf, ServerboundGamePacket)] pub struct ServerboundUseItemOnPacket { pub hand: InteractionHand, - pub block_hit: BlockHitResult, + pub block_hit: BlockHit, #[var] pub sequence: u32, } #[derive(Clone, Debug)] -pub struct BlockHitResult { +pub struct BlockHit { /// The block that we clicked. pub block_pos: BlockPos, /// The face of the block that was clicked. @@ -26,7 +26,7 @@ pub struct BlockHitResult { pub inside: bool, } -impl McBufWritable for BlockHitResult { +impl McBufWritable for BlockHit { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { self.block_pos.write_into(buf)?; self.direction.write_into(buf)?; @@ -47,7 +47,7 @@ impl McBufWritable for BlockHitResult { } } -impl McBufReadable for BlockHitResult { +impl McBufReadable for BlockHit { fn read_from(buf: &mut Cursor<&[u8]>) -> Result { let block_pos = BlockPos::read_from(buf)?; let direction = Direction::read_from(buf)?; diff --git a/azalea-world/src/container.rs b/azalea-world/src/container.rs index c8af8c99..2cf8da8e 100644 --- a/azalea-world/src/container.rs +++ b/azalea-world/src/container.rs @@ -8,7 +8,7 @@ use std::{ sync::{Arc, Weak}, }; -use crate::{ChunkStorage, Instance}; +use crate::{entity::WorldName, ChunkStorage, Instance}; /// A container of [`Instance`]s (aka worlds). Instances are stored as a Weak /// pointer here, so if no clients are using an instance it will be forgotten. @@ -37,7 +37,7 @@ impl InstanceContainer { } /// Get a world from the container. - pub fn get(&self, name: &ResourceLocation) -> Option>> { + pub fn get(&self, name: &WorldName) -> Option>> { self.worlds.get(name).and_then(|world| world.upgrade()) } diff --git a/azalea-world/src/entity/info.rs b/azalea-world/src/entity/info.rs index 3d9aceb5..9cfc4e33 100644 --- a/azalea-world/src/entity/info.rs +++ b/azalea-world/src/entity/info.rs @@ -219,10 +219,10 @@ fn update_entity_chunk_positions( ), Changed, >, - world_container: Res, + instance_container: Res, ) { for (entity, pos, last_pos, world_name) in query.iter_mut() { - let world_lock = world_container.get(world_name).unwrap(); + let world_lock = instance_container.get(world_name).unwrap(); let mut world = world_lock.write(); let old_chunk = ChunkPos::from(*last_pos); @@ -286,11 +286,11 @@ fn debug_detect_updates_received_on_local_entities( fn remove_despawned_entities_from_indexes( mut commands: Commands, mut entity_infos: ResMut, - world_container: Res, + instance_container: Res, query: Query<(Entity, &EntityUuid, &Position, &WorldName, &LoadedBy), Changed>, ) { for (entity, uuid, position, world_name, loaded_by) in &query { - let world_lock = world_container.get(world_name).unwrap(); + let world_lock = instance_container.get(world_name).unwrap(); let mut world = world_lock.write(); // if the entity has no references left, despawn it diff --git a/azalea-world/src/world.rs b/azalea-world/src/world.rs index e8d25032..b9955c9a 100644 --- a/azalea-world/src/world.rs +++ b/azalea-world/src/world.rs @@ -59,11 +59,11 @@ pub fn deduplicate_entities( (Changed, Without), >, mut loaded_by_query: Query<&mut LoadedBy>, - world_container: Res, + instance_container: Res, ) { // if this entity already exists, remove it for (new_entity, id, world_name) in query.iter_mut() { - if let Some(world_lock) = world_container.get(world_name) { + if let Some(world_lock) = instance_container.get(world_name) { let world = world_lock.write(); if let Some(old_entity) = world.entity_by_id.get(id) { if old_entity == &new_entity { @@ -104,11 +104,11 @@ pub fn deduplicate_local_entities( (Entity, &MinecraftEntityId, &WorldName), (Changed, With), >, - world_container: Res, + instance_container: Res, ) { // if this entity already exists, remove the old one for (new_entity, id, world_name) in query.iter_mut() { - if let Some(world_lock) = world_container.get(world_name) { + if let Some(world_lock) = instance_container.get(world_name) { let world = world_lock.write(); if let Some(old_entity) = world.entity_by_id.get(id) { if old_entity == &new_entity { @@ -154,11 +154,11 @@ pub fn update_uuid_index( // mut commands: Commands, // partial_entity_infos: &mut PartialEntityInfos, // chunk: &ChunkPos, -// world_container: &WorldContainer, +// instance_container: &WorldContainer, // world_name: &WorldName, // mut query: Query<(&MinecraftEntityId, &mut ReferenceCount)>, // ) { -// let world_lock = world_container.get(world_name).unwrap(); +// let world_lock = instance_container.get(world_name).unwrap(); // let world = world_lock.read(); // if let Some(entities) = world.entities_by_chunk.get(chunk).cloned() { @@ -290,10 +290,10 @@ pub fn update_entity_by_id_index( (Entity, &MinecraftEntityId, &WorldName, Option<&Local>), Changed, >, - world_container: Res, + instance_container: Res, ) { for (entity, id, world_name, local) in query.iter_mut() { - let world_lock = world_container.get(world_name).unwrap(); + let world_lock = instance_container.get(world_name).unwrap(); let mut world = world_lock.write(); if local.is_none() { if let Some(old_entity) = world.entity_by_id.get(id) { diff --git a/azalea/examples/testbot.rs b/azalea/examples/testbot.rs index 745ce424..84a81be1 100644 --- a/azalea/examples/testbot.rs +++ b/azalea/examples/testbot.rs @@ -202,7 +202,7 @@ async fn swarm_handle( SwarmEvent::Chat(m) => { println!("swarm chat message: {}", m.message().to_ansi()); if m.message().to_string() == " world" { - for (name, world) in &swarm.world_container.read().worlds { + for (name, world) in &swarm.instance_container.read().worlds { println!("world name: {name}"); if let Some(w) = world.upgrade() { for chunk_pos in w.read().chunks.chunks.values() { diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs index 9c06ebb8..56c8e0ce 100644 --- a/azalea/src/pathfinder/mod.rs +++ b/azalea/src/pathfinder/mod.rs @@ -93,7 +93,7 @@ fn goto_listener( mut commands: Commands, mut events: EventReader, mut query: Query<(&Position, &WorldName)>, - world_container: Res, + instance_container: Res, ) { let thread_pool = AsyncComputeTaskPool::get(); @@ -106,7 +106,7 @@ fn goto_listener( vertical_vel: VerticalVel::None, }; - let world_lock = world_container + let world_lock = instance_container .get(world_name) .expect("Entity tried to pathfind but the entity isn't in a valid world"); let end = event.goal.goal_node(); diff --git a/azalea/src/swarm/mod.rs b/azalea/src/swarm/mod.rs index 6fe11b7d..2253f5bd 100644 --- a/azalea/src/swarm/mod.rs +++ b/azalea/src/swarm/mod.rs @@ -37,7 +37,7 @@ pub struct Swarm { // bot_datas: Arc>>, resolved_address: SocketAddr, address: ServerAddress, - pub world_container: Arc>, + pub instance_container: Arc>, bots_tx: mpsc::UnboundedSender<(Option, Client)>, swarm_tx: mpsc::UnboundedSender, @@ -248,7 +248,7 @@ where // resolve the address let resolved_address = resolver::resolve_address(&address).await?; - let world_container = Arc::new(RwLock::new(InstanceContainer::default())); + let instance_container = Arc::new(RwLock::new(InstanceContainer::default())); // we can't modify the swarm plugins after this let (bots_tx, mut bots_rx) = mpsc::unbounded_channel(); @@ -263,7 +263,7 @@ where resolved_address, address, - world_container, + instance_container, bots_tx,