mirror of
https://github.com/italicsjenga/valence.git
synced 2025-01-11 07:11:30 +11:00
Store entity events in the entity struct
This commit is contained in:
parent
e8451da55e
commit
0d07b3659f
|
@ -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::{
|
||||
|
|
|
@ -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;
|
||||
|
|
118
src/entity.rs
118
src/entity.rs
|
@ -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> {
|
||||
|
|
Loading…
Reference in a new issue