mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
update_hit_result_component
This commit is contained in:
parent
34f647781f
commit
babb0d3a74
12 changed files with 86 additions and 54 deletions
|
@ -444,8 +444,8 @@ impl Client {
|
|||
pub fn world(&self) -> Arc<RwLock<Instance>> {
|
||||
let world_name = self.component::<WorldName>();
|
||||
let ecs = self.ecs.lock();
|
||||
let world_container = ecs.resource::<InstanceContainer>();
|
||||
world_container.get(&world_name).unwrap()
|
||||
let instance_container = ecs.resource::<InstanceContainer>();
|
||||
instance_container.get(&world_name).unwrap()
|
||||
}
|
||||
|
||||
/// Returns whether we have a received the login packet yet.
|
||||
|
|
|
@ -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<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 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ fn process_packet_events(ecs: &mut World) {
|
|||
)>,
|
||||
ResMut<InstanceContainer>,
|
||||
)> = 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(),
|
||||
|
|
|
@ -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<BlockHitResult> {
|
||||
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???
|
||||
|
|
|
@ -54,10 +54,10 @@ fn travel(
|
|||
),
|
||||
With<Local>,
|
||||
>,
|
||||
world_container: Res<InstanceContainer>,
|
||||
instance_container: Res<InstanceContainer>,
|
||||
) {
|
||||
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<InstanceContainer>,
|
||||
instance_container: Res<InstanceContainer>,
|
||||
mut events: EventReader<ForceJumpEvent>,
|
||||
) {
|
||||
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();
|
||||
|
|
|
@ -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<Self, BufReadError> {
|
||||
let block_pos = BlockPos::read_from(buf)?;
|
||||
let direction = Direction::read_from(buf)?;
|
||||
|
|
|
@ -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<Arc<RwLock<Instance>>> {
|
||||
pub fn get(&self, name: &WorldName) -> Option<Arc<RwLock<Instance>>> {
|
||||
self.worlds.get(name).and_then(|world| world.upgrade())
|
||||
}
|
||||
|
||||
|
|
|
@ -219,10 +219,10 @@ fn update_entity_chunk_positions(
|
|||
),
|
||||
Changed<entity::Position>,
|
||||
>,
|
||||
world_container: Res<InstanceContainer>,
|
||||
instance_container: Res<InstanceContainer>,
|
||||
) {
|
||||
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<EntityInfos>,
|
||||
world_container: Res<InstanceContainer>,
|
||||
instance_container: Res<InstanceContainer>,
|
||||
query: Query<(Entity, &EntityUuid, &Position, &WorldName, &LoadedBy), Changed<LoadedBy>>,
|
||||
) {
|
||||
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
|
||||
|
|
|
@ -59,11 +59,11 @@ pub fn deduplicate_entities(
|
|||
(Changed<MinecraftEntityId>, Without<Local>),
|
||||
>,
|
||||
mut loaded_by_query: Query<&mut LoadedBy>,
|
||||
world_container: Res<InstanceContainer>,
|
||||
instance_container: Res<InstanceContainer>,
|
||||
) {
|
||||
// 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<MinecraftEntityId>, With<Local>),
|
||||
>,
|
||||
world_container: Res<InstanceContainer>,
|
||||
instance_container: Res<InstanceContainer>,
|
||||
) {
|
||||
// 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<MinecraftEntityId>,
|
||||
>,
|
||||
world_container: Res<InstanceContainer>,
|
||||
instance_container: Res<InstanceContainer>,
|
||||
) {
|
||||
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) {
|
||||
|
|
|
@ -202,7 +202,7 @@ async fn swarm_handle(
|
|||
SwarmEvent::Chat(m) => {
|
||||
println!("swarm chat message: {}", m.message().to_ansi());
|
||||
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}");
|
||||
if let Some(w) = world.upgrade() {
|
||||
for chunk_pos in w.read().chunks.chunks.values() {
|
||||
|
|
|
@ -93,7 +93,7 @@ fn goto_listener(
|
|||
mut commands: Commands,
|
||||
mut events: EventReader<GotoEvent>,
|
||||
mut query: Query<(&Position, &WorldName)>,
|
||||
world_container: Res<InstanceContainer>,
|
||||
instance_container: Res<InstanceContainer>,
|
||||
) {
|
||||
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();
|
||||
|
|
|
@ -37,7 +37,7 @@ pub struct Swarm {
|
|||
// bot_datas: Arc<Mutex<Vec<(Client, S)>>>,
|
||||
resolved_address: SocketAddr,
|
||||
address: ServerAddress,
|
||||
pub world_container: Arc<RwLock<InstanceContainer>>,
|
||||
pub instance_container: Arc<RwLock<InstanceContainer>>,
|
||||
|
||||
bots_tx: mpsc::UnboundedSender<(Option<Event>, Client)>,
|
||||
swarm_tx: mpsc::UnboundedSender<SwarmEvent>,
|
||||
|
@ -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,
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue