1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

update_hit_result_component

This commit is contained in:
mat 2023-03-11 22:33:07 -06:00
parent 34f647781f
commit babb0d3a74
12 changed files with 86 additions and 54 deletions

View file

@ -444,8 +444,8 @@ impl Client {
pub fn world(&self) -> Arc<RwLock<Instance>> { pub fn world(&self) -> Arc<RwLock<Instance>> {
let world_name = self.component::<WorldName>(); let world_name = self.component::<WorldName>();
let ecs = self.ecs.lock(); let ecs = self.ecs.lock();
let world_container = ecs.resource::<InstanceContainer>(); let instance_container = ecs.resource::<InstanceContainer>();
world_container.get(&world_name).unwrap() instance_container.get(&world_name).unwrap()
} }
/// Returns whether we have a received the login packet yet. /// Returns whether we have a received the login packet yet.

View file

@ -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::{ use azalea_protocol::packets::game::{
serverbound_interact_packet::InteractionHand, 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_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 derive_more::{Deref, DerefMut};
use log::warn; 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. /// A plugin that allows clients to interact with blocks in the world.
pub struct InteractPlugin; pub struct InteractPlugin;
@ -73,7 +82,7 @@ fn handle_block_interact_event(
local_player.write_packet( local_player.write_packet(
ServerboundUseItemOnPacket { ServerboundUseItemOnPacket {
hand: InteractionHand::MainHand, hand: InteractionHand::MainHand,
block_hit: BlockHitResult { block_hit: BlockHit {
block_pos: event.position, block_pos: event.position,
direction: Direction::Up, direction: Direction::Up,
location: event.position.center(), location: event.position.center(),
@ -93,15 +102,38 @@ fn update_hit_result_component(
&Position, &Position,
&EyeHeight, &EyeHeight,
&LookDirection, &LookDirection,
&WorldName,
)>, )>,
instance_container: Res<InstanceContainer>,
) { ) {
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 { let pick_range = if game_mode.current == GameMode::Creative {
6. 6.
} else { } else {
4.5 4.5
}; };
let view_vector = view_vector(look_direction); 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;
} }
} }

View file

@ -195,7 +195,7 @@ fn process_packet_events(ecs: &mut World) {
)>, )>,
ResMut<InstanceContainer>, ResMut<InstanceContainer>,
)> = SystemState::new(ecs); )> = 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) = let (mut local_player, world_name, game_profile, client_information) =
query.get_mut(player_entity).unwrap(); query.get_mut(player_entity).unwrap();
@ -221,16 +221,16 @@ fn process_packet_events(ecs: &mut World) {
.entity(player_entity) .entity(player_entity)
.insert(WorldName(new_world_name.clone())); .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) // there)
let weak_world = world_container.insert( let weak_world = instance_container.insert(
new_world_name.clone(), new_world_name.clone(),
dimension.height, dimension.height,
dimension.min_y, dimension.min_y,
); );
// set the partial_world to an empty world // set the partial_world to an empty world
// (when we add chunks or entities those will be in the // (when we add chunks or entities those will be in the
// world_container) // instance_container)
*local_player.partial_instance.write() = PartialInstance::new( *local_player.partial_instance.write() = PartialInstance::new(
client_information.view_distance.into(), client_information.view_distance.into(),

View file

@ -10,9 +10,9 @@ use crate::collision::{BlockWithShape, VoxelShape};
pub struct ClipContext { pub struct ClipContext {
pub from: Vec3, pub from: Vec3,
pub to: Vec3, pub to: Vec3,
pub block: BlockShapeGetter, pub block_shape_type: BlockShapeType,
pub fluid: CanPickFluid, pub fluid_pick_type: FluidPickType,
pub collision_context: EntityCollisionContext, // pub collision_context: EntityCollisionContext,
} }
impl ClipContext { impl ClipContext {
// minecraft passes in the world and blockpos here... but it doesn't actually // 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 { pub fn block_shape(&self, block_state: BlockState) -> &VoxelShape {
// TODO: implement the other shape getters // TODO: implement the other shape getters
// (see the ClipContext.Block class in the vanilla source) // (see the ClipContext.Block class in the vanilla source)
match self.block { match self.block_shape_type {
BlockShapeGetter::Collider => block_state.shape(), BlockShapeType::Collider => block_state.shape(),
BlockShapeGetter::Outline => block_state.shape(), BlockShapeType::Outline => block_state.shape(),
BlockShapeGetter::Visual => block_state.shape(), BlockShapeType::Visual => block_state.shape(),
BlockShapeGetter::FallDamageResetting => block_state.shape(), BlockShapeType::FallDamageResetting => block_state.shape(),
} }
} }
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum BlockShapeGetter { pub enum BlockShapeType {
Collider, Collider,
Outline, Outline,
Visual, Visual,
FallDamageResetting, FallDamageResetting,
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum CanPickFluid { pub enum FluidPickType {
None, None,
SourceOnly, SourceOnly,
Any, Any,
@ -52,7 +52,7 @@ pub struct EntityCollisionContext {
pub entity: Entity, pub entity: Entity,
} }
pub fn clip(chunk_storage: &mut ChunkStorage, context: ClipContext) -> BlockHitResult { pub fn clip(chunk_storage: &ChunkStorage, context: ClipContext) -> BlockHitResult {
traverse_blocks( traverse_blocks(
context.from, context.from,
context.to, context.to,
@ -108,7 +108,7 @@ fn clip_with_interaction_override(
block_state: &BlockState, block_state: &BlockState,
) -> Option<BlockHitResult> { ) -> Option<BlockHitResult> {
let block_hit_result = block_shape.clip(from, to, block_pos); 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 // TODO: minecraft calls .getInteractionShape here
// are there even any blocks that have a physics shape different from the // are there even any blocks that have a physics shape different from the
// interaction shape??? // interaction shape???

View file

@ -54,10 +54,10 @@ fn travel(
), ),
With<Local>, With<Local>,
>, >,
world_container: Res<InstanceContainer>, instance_container: Res<InstanceContainer>,
) { ) {
for (mut physics, direction, mut position, attributes, world_name) in &mut query { 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) .get(world_name)
.expect("All entities should be in a valid world"); .expect("All entities should be in a valid world");
let world = world_lock.read(); let world = world_lock.read();
@ -176,14 +176,14 @@ pub fn force_jump_listener(
&Sprinting, &Sprinting,
&WorldName, &WorldName,
)>, )>,
world_container: Res<InstanceContainer>, instance_container: Res<InstanceContainer>,
mut events: EventReader<ForceJumpEvent>, mut events: EventReader<ForceJumpEvent>,
) { ) {
for event in events.iter() { for event in events.iter() {
if let Ok((mut physics, position, direction, sprinting, world_name)) = if let Ok((mut physics, position, direction, sprinting, world_name)) =
query.get_mut(event.0) query.get_mut(event.0)
{ {
let world_lock = world_container let world_lock = instance_container
.get(world_name) .get(world_name)
.expect("All entities should be in a valid world"); .expect("All entities should be in a valid world");
let world = world_lock.read(); let world = world_lock.read();

View file

@ -7,13 +7,13 @@ use std::io::{Cursor, Write};
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)] #[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundUseItemOnPacket { pub struct ServerboundUseItemOnPacket {
pub hand: InteractionHand, pub hand: InteractionHand,
pub block_hit: BlockHitResult, pub block_hit: BlockHit,
#[var] #[var]
pub sequence: u32, pub sequence: u32,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct BlockHitResult { pub struct BlockHit {
/// The block that we clicked. /// The block that we clicked.
pub block_pos: BlockPos, pub block_pos: BlockPos,
/// The face of the block that was clicked. /// The face of the block that was clicked.
@ -26,7 +26,7 @@ pub struct BlockHitResult {
pub inside: bool, pub inside: bool,
} }
impl McBufWritable for BlockHitResult { impl McBufWritable for BlockHit {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
self.block_pos.write_into(buf)?; self.block_pos.write_into(buf)?;
self.direction.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<Self, BufReadError> { fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
let block_pos = BlockPos::read_from(buf)?; let block_pos = BlockPos::read_from(buf)?;
let direction = Direction::read_from(buf)?; let direction = Direction::read_from(buf)?;

View file

@ -8,7 +8,7 @@ use std::{
sync::{Arc, Weak}, 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 /// 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. /// 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. /// Get a world from the container.
pub fn get(&self, name: &ResourceLocation) -> Option<Arc<RwLock<Instance>>> { pub fn get(&self, name: &WorldName) -> Option<Arc<RwLock<Instance>>> {
self.worlds.get(name).and_then(|world| world.upgrade()) self.worlds.get(name).and_then(|world| world.upgrade())
} }

View file

@ -219,10 +219,10 @@ fn update_entity_chunk_positions(
), ),
Changed<entity::Position>, Changed<entity::Position>,
>, >,
world_container: Res<InstanceContainer>, instance_container: Res<InstanceContainer>,
) { ) {
for (entity, pos, last_pos, world_name) in query.iter_mut() { 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 mut world = world_lock.write();
let old_chunk = ChunkPos::from(*last_pos); 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( fn remove_despawned_entities_from_indexes(
mut commands: Commands, mut commands: Commands,
mut entity_infos: ResMut<EntityInfos>, mut entity_infos: ResMut<EntityInfos>,
world_container: Res<InstanceContainer>, instance_container: Res<InstanceContainer>,
query: Query<(Entity, &EntityUuid, &Position, &WorldName, &LoadedBy), Changed<LoadedBy>>, query: Query<(Entity, &EntityUuid, &Position, &WorldName, &LoadedBy), Changed<LoadedBy>>,
) { ) {
for (entity, uuid, position, world_name, loaded_by) in &query { 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(); let mut world = world_lock.write();
// if the entity has no references left, despawn it // if the entity has no references left, despawn it

View file

@ -59,11 +59,11 @@ pub fn deduplicate_entities(
(Changed<MinecraftEntityId>, Without<Local>), (Changed<MinecraftEntityId>, Without<Local>),
>, >,
mut loaded_by_query: Query<&mut LoadedBy>, mut loaded_by_query: Query<&mut LoadedBy>,
world_container: Res<InstanceContainer>, instance_container: Res<InstanceContainer>,
) { ) {
// if this entity already exists, remove it // if this entity already exists, remove it
for (new_entity, id, world_name) in query.iter_mut() { 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(); let world = world_lock.write();
if let Some(old_entity) = world.entity_by_id.get(id) { if let Some(old_entity) = world.entity_by_id.get(id) {
if old_entity == &new_entity { if old_entity == &new_entity {
@ -104,11 +104,11 @@ pub fn deduplicate_local_entities(
(Entity, &MinecraftEntityId, &WorldName), (Entity, &MinecraftEntityId, &WorldName),
(Changed<MinecraftEntityId>, With<Local>), (Changed<MinecraftEntityId>, With<Local>),
>, >,
world_container: Res<InstanceContainer>, instance_container: Res<InstanceContainer>,
) { ) {
// if this entity already exists, remove the old one // if this entity already exists, remove the old one
for (new_entity, id, world_name) in query.iter_mut() { 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(); let world = world_lock.write();
if let Some(old_entity) = world.entity_by_id.get(id) { if let Some(old_entity) = world.entity_by_id.get(id) {
if old_entity == &new_entity { if old_entity == &new_entity {
@ -154,11 +154,11 @@ pub fn update_uuid_index(
// mut commands: Commands, // mut commands: Commands,
// partial_entity_infos: &mut PartialEntityInfos, // partial_entity_infos: &mut PartialEntityInfos,
// chunk: &ChunkPos, // chunk: &ChunkPos,
// world_container: &WorldContainer, // instance_container: &WorldContainer,
// world_name: &WorldName, // world_name: &WorldName,
// mut query: Query<(&MinecraftEntityId, &mut ReferenceCount)>, // 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(); // let world = world_lock.read();
// if let Some(entities) = world.entities_by_chunk.get(chunk).cloned() { // 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>), (Entity, &MinecraftEntityId, &WorldName, Option<&Local>),
Changed<MinecraftEntityId>, Changed<MinecraftEntityId>,
>, >,
world_container: Res<InstanceContainer>, instance_container: Res<InstanceContainer>,
) { ) {
for (entity, id, world_name, local) in query.iter_mut() { 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(); let mut world = world_lock.write();
if local.is_none() { if local.is_none() {
if let Some(old_entity) = world.entity_by_id.get(id) { if let Some(old_entity) = world.entity_by_id.get(id) {

View file

@ -202,7 +202,7 @@ async fn swarm_handle(
SwarmEvent::Chat(m) => { SwarmEvent::Chat(m) => {
println!("swarm chat message: {}", m.message().to_ansi()); println!("swarm chat message: {}", m.message().to_ansi());
if m.message().to_string() == "<py5> world" { if m.message().to_string() == "<py5> world" {
for (name, world) in &swarm.world_container.read().worlds { for (name, world) in &swarm.instance_container.read().worlds {
println!("world name: {name}"); println!("world name: {name}");
if let Some(w) = world.upgrade() { if let Some(w) = world.upgrade() {
for chunk_pos in w.read().chunks.chunks.values() { for chunk_pos in w.read().chunks.chunks.values() {

View file

@ -93,7 +93,7 @@ fn goto_listener(
mut commands: Commands, mut commands: Commands,
mut events: EventReader<GotoEvent>, mut events: EventReader<GotoEvent>,
mut query: Query<(&Position, &WorldName)>, mut query: Query<(&Position, &WorldName)>,
world_container: Res<InstanceContainer>, instance_container: Res<InstanceContainer>,
) { ) {
let thread_pool = AsyncComputeTaskPool::get(); let thread_pool = AsyncComputeTaskPool::get();
@ -106,7 +106,7 @@ fn goto_listener(
vertical_vel: VerticalVel::None, vertical_vel: VerticalVel::None,
}; };
let world_lock = world_container let world_lock = instance_container
.get(world_name) .get(world_name)
.expect("Entity tried to pathfind but the entity isn't in a valid world"); .expect("Entity tried to pathfind but the entity isn't in a valid world");
let end = event.goal.goal_node(); let end = event.goal.goal_node();

View file

@ -37,7 +37,7 @@ pub struct Swarm {
// bot_datas: Arc<Mutex<Vec<(Client, S)>>>, // bot_datas: Arc<Mutex<Vec<(Client, S)>>>,
resolved_address: SocketAddr, resolved_address: SocketAddr,
address: ServerAddress, address: ServerAddress,
pub world_container: Arc<RwLock<InstanceContainer>>, pub instance_container: Arc<RwLock<InstanceContainer>>,
bots_tx: mpsc::UnboundedSender<(Option<Event>, Client)>, bots_tx: mpsc::UnboundedSender<(Option<Event>, Client)>,
swarm_tx: mpsc::UnboundedSender<SwarmEvent>, swarm_tx: mpsc::UnboundedSender<SwarmEvent>,
@ -248,7 +248,7 @@ where
// resolve the address // resolve the address
let resolved_address = resolver::resolve_address(&address).await?; 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 // we can't modify the swarm plugins after this
let (bots_tx, mut bots_rx) = mpsc::unbounded_channel(); let (bots_tx, mut bots_rx) = mpsc::unbounded_channel();
@ -263,7 +263,7 @@ where
resolved_address, resolved_address,
address, address,
world_container, instance_container,
bots_tx, bots_tx,