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:
parent
bcefa64dd1
commit
f8cca41361
9 changed files with 73 additions and 61 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>,
|
||||
) {
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Add table
Reference in a new issue