mirror of
https://github.com/italicsjenga/valence.git
synced 2025-01-11 15:21:31 +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 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::{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
118
src/entity.rs
118
src/entity.rs
|
@ -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> {
|
||||||
|
|
Loading…
Reference in a new issue