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

fix falling through blocks on spawn (and triggering anticheats)

This commit is contained in:
mat 2023-09-11 22:58:54 -05:00
parent bcefa64dd1
commit f8cca41361
9 changed files with 73 additions and 61 deletions

View file

@ -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

View file

@ -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,
};

View file

@ -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<InstanceContainer>,
) {
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::<LocalPlayerInLoadedChunk>();
}
}
}
/// Send the "Death" event for [`LocalPlayer`]s that died with no reason.
pub fn death_event(query: Query<&LocalPlayerEvents, Added<Dead>>) {
for local_player_events in &query {

View file

@ -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<InLoadedChunk>,
>,
) {
for (
@ -302,7 +302,7 @@ pub fn local_player_ai_step(
&mut Sprinting,
&mut Attributes,
),
With<LocalPlayerInLoadedChunk>,
With<InLoadedChunk>,
>,
) {
for (mut physics_state, mut physics, mut sprinting, mut attributes) in query.iter_mut() {

View file

@ -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(),

View file

@ -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::<EntityUuidIndex>();
}
}
@ -144,3 +145,29 @@ pub fn update_bounding_box(mut query: Query<(&Position, &mut Physics), Changed<P
physics.bounding_box = bounding_box;
}
}
/// Marks an entity that's in a loaded chunk. This is updated at the beginning
/// of every tick.
#[derive(Component, Clone, Debug, Copy)]
pub struct InLoadedChunk;
/// Update the [`InLoadedChunk`] component for all entities in the world.
pub fn update_in_loaded_chunk(
mut commands: bevy_ecs::system::Commands,
query: Query<(Entity, &InstanceName, &Position)>,
instance_container: Res<InstanceContainer>,
) {
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::<InLoadedChunk>();
}
}
}

View file

@ -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

View file

@ -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<Local>,
(With<Local>, With<InLoadedChunk>),
>,
instance_container: Res<InstanceContainer>,
) {
@ -126,10 +132,7 @@ pub fn ai_step(
&Sprinting,
&InstanceName,
),
With<Local>,
// TODO: ai_step should only run for players in loaded chunks
// With<LocalPlayerInLoadedChunk> maybe there should be an InLoadedChunk/InUnloadedChunk
// component?
(With<Local>, With<InLoadedChunk>),
>,
instance_container: Res<InstanceContainer>,
) {

View file

@ -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),