mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 14:31:30 +11:00
Reimplement client self-exclusion (#314)
## Description Stops packets for the client's own entity being sent back to the client. This prevents the "ghost player" from appearing at spawn. ## Test Plan Steps: 1. `cargo r --example bench_players` 2. Press F3 3. Look at where the player spawned. Notice that there is no ghost player entity. 4. Look at received packets `rx`. Moving around in a chunk, you will not receive packets for the player's own entity. `rx` should be close to zero.
This commit is contained in:
parent
cd8a9266ef
commit
1c405ab63c
|
@ -39,7 +39,7 @@ use crate::component::{
|
|||
Properties, UniqueId, Username,
|
||||
};
|
||||
use crate::entity::{
|
||||
EntityId, EntityKind, EntityStatus, HeadYaw, ObjectData, TrackedData, Velocity,
|
||||
EntityId, EntityKind, EntityStatus, HeadYaw, ObjectData, PacketByteRange, TrackedData, Velocity,
|
||||
};
|
||||
use crate::instance::{Instance, WriteUpdatePacketsToInstancesSet};
|
||||
use crate::inventory::{Inventory, InventoryKind};
|
||||
|
@ -859,16 +859,19 @@ fn read_data_in_old_view(
|
|||
mut clients: Query<(
|
||||
&mut Client,
|
||||
&mut EntityRemoveBuf,
|
||||
&Location,
|
||||
&OldLocation,
|
||||
&Position,
|
||||
&OldPosition,
|
||||
&OldViewDistance,
|
||||
Option<&PacketByteRange>,
|
||||
)>,
|
||||
instances: Query<&Instance>,
|
||||
entities: Query<(EntityInitQuery, &OldPosition)>,
|
||||
entity_ids: Query<&EntityId>,
|
||||
) {
|
||||
clients.par_iter_mut().for_each_mut(
|
||||
|(mut client, mut remove_buf, old_loc, old_pos, old_view_dist)| {
|
||||
|(mut client, mut remove_buf, loc, old_loc, pos, old_pos, old_view_dist, byte_range)| {
|
||||
let Ok(instance) = instances.get(old_loc.get()) else {
|
||||
return;
|
||||
};
|
||||
|
@ -877,9 +880,10 @@ fn read_data_in_old_view(
|
|||
client.write_packet_bytes(&instance.packet_buf);
|
||||
|
||||
// TODO: cache the chunk position?
|
||||
let chunk_pos = old_pos.chunk_pos();
|
||||
let old_chunk_pos = old_pos.chunk_pos();
|
||||
let new_chunk_pos = pos.chunk_pos();
|
||||
|
||||
let view = ChunkView::new(chunk_pos, old_view_dist.0);
|
||||
let view = ChunkView::new(old_chunk_pos, old_view_dist.0);
|
||||
|
||||
// Iterate over all visible chunks from the previous tick.
|
||||
view.for_each(|pos| {
|
||||
|
@ -925,8 +929,17 @@ fn read_data_in_old_view(
|
|||
// Send all data in the chunk's packet buffer to this client. This will update
|
||||
// entities in the cell, spawn or update the chunk in the cell, or send any
|
||||
// other packet data that was added here by users.
|
||||
match byte_range {
|
||||
Some(byte_range) if pos == new_chunk_pos && loc == old_loc => {
|
||||
// Skip range of bytes for the client's own entity.
|
||||
client.write_packet_bytes(&cell.packet_buf[..byte_range.0.start]);
|
||||
client.write_packet_bytes(&cell.packet_buf[byte_range.0.end..]);
|
||||
}
|
||||
_ => {
|
||||
client.write_packet_bytes(&cell.packet_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
@ -940,6 +953,7 @@ fn read_data_in_old_view(
|
|||
fn update_view(
|
||||
mut clients: Query<
|
||||
(
|
||||
Entity,
|
||||
&mut Client,
|
||||
&mut ScratchBuf,
|
||||
&mut EntityRemoveBuf,
|
||||
|
@ -958,6 +972,7 @@ fn update_view(
|
|||
) {
|
||||
clients.par_iter_mut().for_each_mut(
|
||||
|(
|
||||
entity,
|
||||
mut client,
|
||||
mut scratch,
|
||||
mut remove_buf,
|
||||
|
@ -1000,11 +1015,14 @@ fn update_view(
|
|||
|
||||
// Unload all the entities in the cell.
|
||||
for &id in &cell.entities {
|
||||
// Skip client's own entity.
|
||||
if id != entity {
|
||||
if let Ok(entity_id) = entity_ids.get(id) {
|
||||
remove_buf.push(entity_id.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1026,11 +1044,14 @@ fn update_view(
|
|||
|
||||
// Load all the entities in this cell.
|
||||
for &id in &cell.entities {
|
||||
// Skip client's own entity.
|
||||
if id != entity {
|
||||
if let Ok((entity, pos)) = entities.get(id) {
|
||||
entity.write_init_packets(pos.get(), &mut client.enc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
warn!("Client entered nonexistent instance ({loc:?}).");
|
||||
|
|
|
@ -120,6 +120,12 @@ impl Default for Location {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<OldLocation> for Location {
|
||||
fn eq(&self, other: &OldLocation) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
||||
/// The value of [`Location`] from the end of the previous tick.
|
||||
///
|
||||
/// **NOTE**: You should not modify this component after the entity is spawned.
|
||||
|
@ -142,6 +148,12 @@ impl Default for OldLocation {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Location> for OldLocation {
|
||||
fn eq(&self, other: &Location) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Copy, Clone, PartialEq, Default, Debug)]
|
||||
pub struct Position(pub DVec3);
|
||||
|
||||
|
@ -163,6 +175,12 @@ impl Position {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<OldPosition> for Position {
|
||||
fn eq(&self, other: &OldPosition) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
||||
/// The value of [`Location`] from the end of the previous tick.
|
||||
///
|
||||
/// **NOTE**: You should not modify this component after the entity is spawned.
|
||||
|
@ -183,6 +201,12 @@ impl OldPosition {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Position> for OldPosition {
|
||||
fn eq(&self, other: &Position) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the direction an entity is looking using pitch and yaw angles.
|
||||
#[derive(Component, Copy, Clone, PartialEq, Default, Debug)]
|
||||
pub struct Look {
|
||||
|
|
Loading…
Reference in a new issue