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:
Ryan Johnson 2023-04-05 17:56:30 -07:00 committed by GitHub
parent cd8a9266ef
commit 1c405ab63c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 9 deletions

View file

@ -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:?}).");

View file

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