Store entity events in the entity struct

This commit is contained in:
Ryan 2022-07-04 00:24:55 -07:00
parent e8451da55e
commit 0d07b3659f
3 changed files with 107 additions and 92 deletions

View file

@ -7,7 +7,7 @@ use std::sync::Mutex;
use log::LevelFilter;
use num::Integer;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator};
use valence::client::{ClientId, ClientEvent, GameMode, EntityEvent};
use valence::client::{ClientId, ClientEvent, GameMode};
use valence::config::{Config, ServerListPing};
use valence::text::Color;
use valence::{

View file

@ -145,7 +145,7 @@ pub struct Client {
settings: Option<Settings>,
dug_blocks: Vec<i32>,
msgs_to_send: Vec<Text>,
entity_events: Vec<(Option<EntityId>, EntityEvent)>,
entity_events: Vec<EntityEvent>,
/// The metadata for the client's own player entity.
player_meta: Player,
}
@ -316,8 +316,8 @@ impl Client {
self.events.pop_front()
}
pub fn push_entity_event(&mut self, target: Option<EntityId>, event: EntityEvent) {
self.entity_events.push((target, event));
pub fn push_entity_event(&mut self, event: EntityEvent) {
self.entity_events.push(event);
}
/// The current view distance of this client measured in chunks.
@ -838,9 +838,7 @@ impl Client {
self.loaded_entities.retain(|&id| {
if let Some(entity) = entities.get(id) {
debug_assert!(entity.typ() != EntityType::Marker);
if self.new_position.distance(entity.position()) <= view_dist as f64 * 16.0
&& !entity.flags().type_modified()
{
if self.new_position.distance(entity.position()) <= view_dist as f64 * 16.0 {
if let Some(meta) = entity.updated_metadata_packet(id) {
send_packet(&mut self.send, meta);
}
@ -921,6 +919,16 @@ impl Client {
)
}
for &e in entity.events() {
send_packet(
&mut self.send,
EntityEventPacket {
entity_id: id.to_network_id(),
entity_status: e,
},
);
}
return true;
}
}
@ -954,44 +962,41 @@ impl Client {
world.spatial_index.query::<_, _, ()>(
|bb| bb.projected_point(pos).distance(pos) <= view_dist as f64 * 16.0,
|id, _| {
if self.loaded_entities.insert(id) {
let entity = entities.get(id).unwrap();
if entity.typ() != EntityType::Marker {
self.send_packet(
entity
.spawn_packet(id)
.expect("should not be a marker entity"),
);
let entity = entities.get(id).unwrap();
if entity.typ() != EntityType::Marker && self.loaded_entities.insert(id) {
self.send_packet(
entity
.spawn_packet(id)
.expect("should not be a marker entity"),
);
if let Some(meta) = entity.initial_metadata_packet(id) {
self.send_packet(meta);
}
if let Some(meta) = entity.initial_metadata_packet(id) {
self.send_packet(meta);
}
for &e in entity.events() {
send_packet(
&mut self.send,
EntityEventPacket {
entity_id: id.to_network_id(),
entity_status: e,
},
);
}
}
None
},
);
for (target, event) in self.entity_events.drain(..) {
if let Some(target) = target {
if self.loaded_entities.contains(&target) {
send_packet(
&mut self.send,
EntityEventPacket {
entity_id: target.to_network_id(),
entity_status: event,
},
)
}
} else {
send_packet(
&mut self.send,
EntityEventPacket {
entity_id: 0,
entity_status: event,
},
);
}
// Send entity events for the client's own player entity.
for event in self.entity_events.drain(..) {
send_packet(
&mut self.send,
EntityEventPacket {
entity_id: 0,
entity_status: event,
},
);
}
self.old_position = self.new_position;

View file

@ -12,6 +12,7 @@ pub use types::{EntityMeta, EntityType};
use uuid::Uuid;
use vek::{Aabb, Vec3};
pub use crate::protocol::packets::play::s2c::EntityEventStatus as EntityEvent;
use crate::protocol::packets::play::s2c::{
AddEntity, AddExperienceOrb, AddPlayer, S2cPlayPacket, SetEntityMetadata,
};
@ -66,6 +67,7 @@ impl Entities {
head_yaw: 0.0,
velocity: Vec3::default(),
uuid,
events: Vec::new(),
});
ve.insert(EntityId(k));
@ -157,10 +159,11 @@ impl Entities {
for (_, e) in self.iter_mut() {
e.old_position = e.new_position;
e.meta.clear_modifications();
e.events.clear();
let on_ground = e.flags.on_ground();
e.flags = EntityFlags(0);
e.flags.set_on_ground(on_ground);
e.flags.set_yaw_or_pitch_modified(false);
e.flags.set_head_yaw_modified(false);
e.flags.set_velocity_modified(false);
}
}
}
@ -187,19 +190,18 @@ pub struct Entity {
head_yaw: f32,
velocity: Vec3<f32>,
uuid: Uuid,
events: Vec<EntityEvent>,
}
/// Contains a bit for certain fields in [`Entity`] to track if they have been
/// modified.
#[bitfield(u8)]
pub(crate) struct EntityFlags {
/// When the type of this entity changes.
pub type_modified: bool,
pub yaw_or_pitch_modified: bool,
pub head_yaw_modified: bool,
pub velocity_modified: bool,
pub on_ground: bool,
#[bits(3)]
#[bits(4)]
_pad: u8,
}
@ -308,56 +310,12 @@ impl Entity {
self.flags.set_on_ground(on_ground);
}
/// Gets the metadata packet to send to clients after this entity has been
/// spawned.
///
/// Is `None` if there is no initial metadata.
pub(crate) fn initial_metadata_packet(&self, this_id: EntityId) -> Option<SetEntityMetadata> {
self.meta.initial_metadata().map(|meta| SetEntityMetadata {
entity_id: VarInt(this_id.to_network_id()),
metadata: RawBytes(meta),
})
pub fn push_event(&mut self, event: EntityEvent) {
self.events.push(event);
}
/// Gets the metadata packet to send to clients when the entity is modified.
///
/// Is `None` if this entity's metadata has not been modified.
pub(crate) fn updated_metadata_packet(&self, this_id: EntityId) -> Option<SetEntityMetadata> {
self.meta.updated_metadata().map(|meta| SetEntityMetadata {
entity_id: VarInt(this_id.to_network_id()),
metadata: RawBytes(meta),
})
}
pub(crate) fn spawn_packet(&self, this_id: EntityId) -> Option<EntitySpawnPacket> {
match &self.meta {
EntityMeta::Marker(_) => None,
EntityMeta::ExperienceOrb(_) => {
Some(EntitySpawnPacket::SpawnExperienceOrb(AddExperienceOrb {
entity_id: VarInt(this_id.to_network_id()),
position: self.new_position,
count: 0, // TODO
}))
}
EntityMeta::Player(_) => Some(EntitySpawnPacket::SpawnPlayer(AddPlayer {
entity_id: VarInt(this_id.to_network_id()),
player_uuid: self.uuid,
position: self.new_position,
yaw: ByteAngle::from_degrees(self.yaw),
pitch: ByteAngle::from_degrees(self.pitch),
})),
_ => Some(EntitySpawnPacket::SpawnEntity(AddEntity {
entity_id: VarInt(this_id.to_network_id()),
object_uuid: self.uuid,
typ: VarInt(self.typ() as i32),
position: self.new_position,
pitch: ByteAngle::from_degrees(self.pitch),
yaw: ByteAngle::from_degrees(self.yaw),
head_yaw: ByteAngle::from_degrees(self.head_yaw),
data: VarInt(1), // TODO
velocity: velocity_to_packet_units(self.velocity),
})),
}
pub(crate) fn events(&self) -> &[EntityEvent] {
&self.events
}
pub fn hitbox(&self) -> Aabb<f64> {
@ -502,6 +460,58 @@ impl Entity {
aabb_from_bottom_and_size(self.new_position, dims.into())
}
/// Gets the metadata packet to send to clients after this entity has been
/// spawned.
///
/// Is `None` if there is no initial metadata.
pub(crate) fn initial_metadata_packet(&self, this_id: EntityId) -> Option<SetEntityMetadata> {
self.meta.initial_metadata().map(|meta| SetEntityMetadata {
entity_id: VarInt(this_id.to_network_id()),
metadata: RawBytes(meta),
})
}
/// Gets the metadata packet to send to clients when the entity is modified.
///
/// Is `None` if this entity's metadata has not been modified.
pub(crate) fn updated_metadata_packet(&self, this_id: EntityId) -> Option<SetEntityMetadata> {
self.meta.updated_metadata().map(|meta| SetEntityMetadata {
entity_id: VarInt(this_id.to_network_id()),
metadata: RawBytes(meta),
})
}
pub(crate) fn spawn_packet(&self, this_id: EntityId) -> Option<EntitySpawnPacket> {
match &self.meta {
EntityMeta::Marker(_) => None,
EntityMeta::ExperienceOrb(_) => {
Some(EntitySpawnPacket::SpawnExperienceOrb(AddExperienceOrb {
entity_id: VarInt(this_id.to_network_id()),
position: self.new_position,
count: 0, // TODO
}))
}
EntityMeta::Player(_) => Some(EntitySpawnPacket::SpawnPlayer(AddPlayer {
entity_id: VarInt(this_id.to_network_id()),
player_uuid: self.uuid,
position: self.new_position,
yaw: ByteAngle::from_degrees(self.yaw),
pitch: ByteAngle::from_degrees(self.pitch),
})),
_ => Some(EntitySpawnPacket::SpawnEntity(AddEntity {
entity_id: VarInt(this_id.to_network_id()),
object_uuid: self.uuid,
typ: VarInt(self.typ() as i32),
position: self.new_position,
pitch: ByteAngle::from_degrees(self.pitch),
yaw: ByteAngle::from_degrees(self.yaw),
head_yaw: ByteAngle::from_degrees(self.head_yaw),
data: VarInt(1), // TODO
velocity: velocity_to_packet_units(self.velocity),
})),
}
}
}
pub(crate) fn velocity_to_packet_units(vel: Vec3<f32>) -> Vec3<i16> {