From f8cca413613918a59520ac62c188e194fa27b300 Mon Sep 17 00:00:00 2001 From: mat Date: Mon, 11 Sep 2023 22:58:54 -0500 Subject: [PATCH] fix falling through blocks on spawn (and triggering anticheats) --- azalea-client/src/client.rs | 5 +-- azalea-client/src/lib.rs | 2 +- azalea-client/src/local_player.rs | 40 +++---------------- azalea-client/src/movement.rs | 8 ++-- azalea-client/src/packet_handling.rs | 24 ++++++++--- azalea-entity/src/plugin/mod.rs | 31 +++++++++++++- .../src/collision/world_collisions.rs | 4 +- azalea-physics/src/lib.rs | 19 +++++---- azalea/src/pathfinder/simulation.rs | 1 - 9 files changed, 73 insertions(+), 61 deletions(-) diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 517db4e9..332db1f1 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -6,8 +6,8 @@ use crate::{ interact::{CurrentSequenceNumber, InteractPlugin}, inventory::{InventoryComponent, InventoryPlugin}, local_player::{ - death_event, handle_send_packet_event, update_in_loaded_chunk, GameProfileComponent, - Hunger, LocalPlayer, SendPacketEvent, + death_event, handle_send_packet_event, GameProfileComponent, Hunger, LocalPlayer, + SendPacketEvent, }, mining::{self, MinePlugin}, movement::{LastSentLookDirection, PhysicsState, PlayerMovePlugin}, @@ -617,7 +617,6 @@ impl Plugin for AzaleaPlugin { .add_systems( Update, ( - update_in_loaded_chunk, // fire the Death event when the player dies. death_event, // add GameProfileComponent when we get an AddPlayerEvent diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs index 4cb1eebf..8ea2fc41 100644 --- a/azalea-client/src/lib.rs +++ b/azalea-client/src/lib.rs @@ -36,7 +36,7 @@ pub use client::{ TickBroadcast, }; pub use events::Event; -pub use local_player::{GameProfileComponent, LocalPlayer, LocalPlayerInLoadedChunk}; +pub use local_player::{GameProfileComponent, LocalPlayer}; pub use movement::{ PhysicsState, SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection, }; diff --git a/azalea-client/src/local_player.rs b/azalea-client/src/local_player.rs index 682fc0c9..0c89b4a7 100644 --- a/azalea-client/src/local_player.rs +++ b/azalea-client/src/local_player.rs @@ -1,17 +1,13 @@ use std::{io, sync::Arc}; use azalea_auth::game_profile::GameProfile; -use azalea_core::{ChunkPos, GameMode}; -use azalea_entity::{Dead, Position}; +use azalea_core::GameMode; +use azalea_entity::Dead; use azalea_protocol::packets::game::ServerboundGamePacket; -use azalea_world::{Instance, InstanceContainer, InstanceName, PartialInstance}; +use azalea_world::{Instance, PartialInstance}; use bevy_ecs::{ - component::Component, - entity::Entity, - event::EventReader, - prelude::Event, - query::Added, - system::{Query, Res}, + component::Component, entity::Entity, event::EventReader, prelude::Event, query::Added, + system::Query, }; use derive_more::{Deref, DerefMut}; use parking_lot::RwLock; @@ -59,11 +55,6 @@ pub struct LocalPlayer { #[derive(Component, Clone, Debug, Deref, DerefMut)] pub struct GameProfileComponent(pub GameProfile); -/// Marks a [`LocalPlayer`] that's in a loaded chunk. This is updated at the -/// beginning of every tick. -#[derive(Component, Clone, Debug, Copy)] -pub struct LocalPlayerInLoadedChunk; - /// The gamemode of a local player. For a non-local player, you can look up the /// player in the [`TabList`]. #[derive(Component, Clone, Debug, Copy)] @@ -134,27 +125,6 @@ impl Drop for LocalPlayer { } } -/// Update the [`LocalPlayerInLoadedChunk`] component for all [`LocalPlayer`]s. -pub fn update_in_loaded_chunk( - mut commands: bevy_ecs::system::Commands, - query: Query<(Entity, &InstanceName, &Position)>, - instance_container: Res, -) { - for (entity, local_player, position) in &query { - let player_chunk_pos = ChunkPos::from(position); - let Some(instance_lock) = instance_container.get(local_player) else { - continue; - }; - - let in_loaded_chunk = instance_lock.read().chunks.get(&player_chunk_pos).is_some(); - if in_loaded_chunk { - commands.entity(entity).insert(LocalPlayerInLoadedChunk); - } else { - commands.entity(entity).remove::(); - } - } -} - /// Send the "Death" event for [`LocalPlayer`]s that died with no reason. pub fn death_event(query: Query<&LocalPlayerEvents, Added>) { for local_player_events in &query { diff --git a/azalea-client/src/movement.rs b/azalea-client/src/movement.rs index 351d91be..47cbd0ac 100644 --- a/azalea-client/src/movement.rs +++ b/azalea-client/src/movement.rs @@ -1,7 +1,7 @@ use crate::client::Client; -use crate::local_player::{LocalPlayer, LocalPlayerInLoadedChunk}; +use crate::local_player::LocalPlayer; use azalea_entity::{metadata::Sprinting, Attributes, Jumping}; -use azalea_entity::{LastSentPosition, LookDirection, Physics, Position}; +use azalea_entity::{InLoadedChunk, LastSentPosition, LookDirection, Physics, Position}; use azalea_physics::PhysicsSet; use azalea_protocol::packets::game::serverbound_player_command_packet::ServerboundPlayerCommandPacket; use azalea_protocol::packets::game::{ @@ -128,7 +128,7 @@ pub fn send_position( &mut LastSentLookDirection, &Sprinting, ), - &LocalPlayerInLoadedChunk, + With, >, ) { for ( @@ -302,7 +302,7 @@ pub fn local_player_ai_step( &mut Sprinting, &mut Attributes, ), - With, + With, >, ) { for (mut physics_state, mut physics, mut sprinting, mut attributes) in query.iter_mut() { diff --git a/azalea-client/src/packet_handling.rs b/azalea-client/src/packet_handling.rs index 605da379..c2a01659 100644 --- a/azalea-client/src/packet_handling.rs +++ b/azalea-client/src/packet_handling.rs @@ -709,14 +709,18 @@ pub fn process_packet_events(ecs: &mut World) { ClientboundGamePacket::TeleportEntity(p) => { let mut system_state: SystemState<( Commands, - Query<(&EntityIdIndex, &LocalPlayer)>, + Query<(&EntityIdIndex, &LocalPlayer, Option<&mut Physics>)>, )> = SystemState::new(ecs); let (mut commands, mut query) = system_state.get_mut(ecs); - let (entity_id_index, local_player) = query.get_mut(player_entity).unwrap(); + let (entity_id_index, local_player, physics) = + query.get_mut(player_entity).unwrap(); let entity = entity_id_index.get(&MinecraftEntityId(p.id)); if let Some(entity) = entity { + if let Some(mut physics) = physics { + physics.on_ground = p.on_ground; + } let new_position = p.position; commands.entity(entity).add(RelativeEntityUpdate { partial_world: local_player.partial_instance.clone(), @@ -740,14 +744,18 @@ pub fn process_packet_events(ecs: &mut World) { ClientboundGamePacket::MoveEntityPos(p) => { let mut system_state: SystemState<( Commands, - Query<(&EntityIdIndex, &LocalPlayer)>, + Query<(&EntityIdIndex, &LocalPlayer, Option<&mut Physics>)>, )> = SystemState::new(ecs); let (mut commands, mut query) = system_state.get_mut(ecs); - let (entity_id_index, local_player) = query.get_mut(player_entity).unwrap(); + let (entity_id_index, local_player, physics) = + query.get_mut(player_entity).unwrap(); let entity = entity_id_index.get(&MinecraftEntityId(p.entity_id)); if let Some(entity) = entity { + if let Some(mut physics) = physics { + physics.on_ground = p.on_ground; + } let delta = p.delta.clone(); commands.entity(entity).add(RelativeEntityUpdate { partial_world: local_player.partial_instance.clone(), @@ -768,14 +776,18 @@ pub fn process_packet_events(ecs: &mut World) { ClientboundGamePacket::MoveEntityPosRot(p) => { let mut system_state: SystemState<( Commands, - Query<(&EntityIdIndex, &LocalPlayer)>, + Query<(&EntityIdIndex, &LocalPlayer, Option<&mut Physics>)>, )> = SystemState::new(ecs); let (mut commands, mut query) = system_state.get_mut(ecs); - let (entity_id_index, local_player) = query.get_mut(player_entity).unwrap(); + let (entity_id_index, local_player, physics) = + query.get_mut(player_entity).unwrap(); let entity = entity_id_index.get(&MinecraftEntityId(p.entity_id)); if let Some(entity) = entity { + if let Some(mut physics) = physics { + physics.on_ground = p.on_ground; + } let delta = p.delta.clone(); commands.entity(entity).add(RelativeEntityUpdate { partial_world: local_player.partial_instance.clone(), diff --git a/azalea-entity/src/plugin/mod.rs b/azalea-entity/src/plugin/mod.rs index 94e8e79d..6153ac17 100644 --- a/azalea-entity/src/plugin/mod.rs +++ b/azalea-entity/src/plugin/mod.rs @@ -3,9 +3,9 @@ mod relative_updates; use std::collections::HashSet; -use azalea_core::{BlockPos, Vec3}; +use azalea_core::{BlockPos, ChunkPos, Vec3}; use azalea_world::{InstanceContainer, InstanceName, MinecraftEntityId}; -use bevy_app::{App, Plugin, PostUpdate, PreUpdate, Update}; +use bevy_app::{App, FixedUpdate, Plugin, PostUpdate, PreUpdate, Update}; use bevy_ecs::prelude::*; use derive_more::{Deref, DerefMut}; use log::debug; @@ -68,6 +68,7 @@ impl Plugin for EntityPlugin { ), ) .add_systems(Update, update_bounding_box) + .add_systems(FixedUpdate, update_in_loaded_chunk) .init_resource::(); } } @@ -144,3 +145,29 @@ pub fn update_bounding_box(mut query: Query<(&Position, &mut Physics), Changed

, + instance_container: Res, +) { + for (entity, instance_name, position) in &query { + let player_chunk_pos = ChunkPos::from(position); + let Some(instance_lock) = instance_container.get(instance_name) else { + continue; + }; + + let in_loaded_chunk = instance_lock.read().chunks.get(&player_chunk_pos).is_some(); + if in_loaded_chunk { + commands.entity(entity).insert(InLoadedChunk); + } else { + commands.entity(entity).remove::(); + } + } +} diff --git a/azalea-physics/src/collision/world_collisions.rs b/azalea-physics/src/collision/world_collisions.rs index e640f0ce..414b4c58 100644 --- a/azalea-physics/src/collision/world_collisions.rs +++ b/azalea-physics/src/collision/world_collisions.rs @@ -71,7 +71,9 @@ impl<'a> Iterator for BlockCollisions<'a> { } let chunk = self.get_chunk(item.pos.x, item.pos.z); - let Some(chunk) = chunk else { continue }; + let Some(chunk) = chunk else { + continue; + }; let pos = item.pos; let block_state: BlockState = chunk diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs index 06138cf7..143f99ab 100644 --- a/azalea-physics/src/lib.rs +++ b/azalea-physics/src/lib.rs @@ -7,8 +7,8 @@ pub mod collision; use azalea_block::{Block, BlockState}; use azalea_core::{math, BlockPos, Vec3}; use azalea_entity::{ - metadata::Sprinting, move_relative, Attributes, Jumping, Local, LookDirection, Physics, - Position, + metadata::Sprinting, move_relative, Attributes, InLoadedChunk, Jumping, Local, LookDirection, + Physics, Position, }; use azalea_world::{Instance, InstanceContainer, InstanceName}; use bevy_app::{App, FixedUpdate, Plugin}; @@ -26,7 +26,13 @@ pub struct PhysicsSet; pub struct PhysicsPlugin; impl Plugin for PhysicsPlugin { fn build(&self, app: &mut App) { - app.add_systems(FixedUpdate, (ai_step, travel).chain().in_set(PhysicsSet)); + app.add_systems( + FixedUpdate, + (ai_step, travel) + .chain() + .in_set(PhysicsSet) + .after(azalea_entity::update_in_loaded_chunk), + ); } } @@ -43,7 +49,7 @@ fn travel( &Attributes, &InstanceName, ), - With, + (With, With), >, instance_container: Res, ) { @@ -126,10 +132,7 @@ pub fn ai_step( &Sprinting, &InstanceName, ), - With, - // TODO: ai_step should only run for players in loaded chunks - // With maybe there should be an InLoadedChunk/InUnloadedChunk - // component? + (With, With), >, instance_container: Res, ) { diff --git a/azalea/src/pathfinder/simulation.rs b/azalea/src/pathfinder/simulation.rs index 9ee77052..a61b823f 100644 --- a/azalea/src/pathfinder/simulation.rs +++ b/azalea/src/pathfinder/simulation.rs @@ -84,7 +84,6 @@ impl Simulation { MinecraftEntityId(0), InstanceName(instance_name), azalea_entity::Local, - azalea_client::LocalPlayerInLoadedChunk, azalea_entity::Jumping::default(), azalea_entity::LookDirection::default(), Sprinting(true),