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 log::LevelFilter;
use num::Integer; use num::Integer;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator}; 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::config::{Config, ServerListPing};
use valence::text::Color; use valence::text::Color;
use valence::{ use valence::{

View file

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

View file

@ -12,6 +12,7 @@ pub use types::{EntityMeta, EntityType};
use uuid::Uuid; use uuid::Uuid;
use vek::{Aabb, Vec3}; use vek::{Aabb, Vec3};
pub use crate::protocol::packets::play::s2c::EntityEventStatus as EntityEvent;
use crate::protocol::packets::play::s2c::{ use crate::protocol::packets::play::s2c::{
AddEntity, AddExperienceOrb, AddPlayer, S2cPlayPacket, SetEntityMetadata, AddEntity, AddExperienceOrb, AddPlayer, S2cPlayPacket, SetEntityMetadata,
}; };
@ -66,6 +67,7 @@ impl Entities {
head_yaw: 0.0, head_yaw: 0.0,
velocity: Vec3::default(), velocity: Vec3::default(),
uuid, uuid,
events: Vec::new(),
}); });
ve.insert(EntityId(k)); ve.insert(EntityId(k));
@ -157,10 +159,11 @@ impl Entities {
for (_, e) in self.iter_mut() { for (_, e) in self.iter_mut() {
e.old_position = e.new_position; e.old_position = e.new_position;
e.meta.clear_modifications(); e.meta.clear_modifications();
e.events.clear();
let on_ground = e.flags.on_ground(); e.flags.set_yaw_or_pitch_modified(false);
e.flags = EntityFlags(0); e.flags.set_head_yaw_modified(false);
e.flags.set_on_ground(on_ground); e.flags.set_velocity_modified(false);
} }
} }
} }
@ -187,19 +190,18 @@ pub struct Entity {
head_yaw: f32, head_yaw: f32,
velocity: Vec3<f32>, velocity: Vec3<f32>,
uuid: Uuid, uuid: Uuid,
events: Vec<EntityEvent>,
} }
/// Contains a bit for certain fields in [`Entity`] to track if they have been /// Contains a bit for certain fields in [`Entity`] to track if they have been
/// modified. /// modified.
#[bitfield(u8)] #[bitfield(u8)]
pub(crate) struct EntityFlags { pub(crate) struct EntityFlags {
/// When the type of this entity changes.
pub type_modified: bool,
pub yaw_or_pitch_modified: bool, pub yaw_or_pitch_modified: bool,
pub head_yaw_modified: bool, pub head_yaw_modified: bool,
pub velocity_modified: bool, pub velocity_modified: bool,
pub on_ground: bool, pub on_ground: bool,
#[bits(3)] #[bits(4)]
_pad: u8, _pad: u8,
} }
@ -308,56 +310,12 @@ impl Entity {
self.flags.set_on_ground(on_ground); self.flags.set_on_ground(on_ground);
} }
/// Gets the metadata packet to send to clients after this entity has been pub fn push_event(&mut self, event: EntityEvent) {
/// spawned. self.events.push(event);
///
/// 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. pub(crate) fn events(&self) -> &[EntityEvent] {
/// &self.events
/// 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 fn hitbox(&self) -> Aabb<f64> { pub fn hitbox(&self) -> Aabb<f64> {
@ -502,6 +460,58 @@ impl Entity {
aabb_from_bottom_and_size(self.new_position, dims.into()) 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> { pub(crate) fn velocity_to_packet_units(vel: Vec3<f32>) -> Vec3<i16> {