-
Notifications
You must be signed in to change notification settings - Fork 144
Expand file tree
/
Copy pathentity.rs
More file actions
109 lines (97 loc) · 3.59 KB
/
entity.rs
File metadata and controls
109 lines (97 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! Sends entity-related packets to clients.
//! Spawn packets, position updates, equipment, animations, etc.
use base::{
metadata::{EntityBitMask, Pose, META_INDEX_ENTITY_BITMASK, META_INDEX_POSE},
EntityMetadata, Position,
};
use common::Game;
use ecs::{SysResult, SystemExecutor};
use quill_common::{
components::{OnGround, Sprinting},
events::{SneakEvent, SprintEvent},
};
use crate::{
entities::{PreviousOnGround, PreviousPosition},
NetworkId, Server,
};
mod spawn_packet;
pub fn register(game: &mut Game, systems: &mut SystemExecutor<Game>) {
spawn_packet::register(game, systems);
systems
.group::<Server>()
.add_system(send_entity_movement)
.add_system(send_entity_sneak_metadata)
.add_system(send_entity_sprint_metadata);
}
/// Sends entity movement packets.
fn send_entity_movement(game: &mut Game, server: &mut Server) -> SysResult {
for (_, (&position, prev_position, &on_ground, &network_id, prev_on_ground)) in game
.ecs
.query::<(
&Position,
&mut PreviousPosition,
&OnGround,
&NetworkId,
&mut PreviousOnGround,
)>()
.iter()
{
if position != prev_position.0 {
server.broadcast_nearby_with(position, |client| {
client.update_entity_position(
network_id,
position,
*prev_position,
on_ground,
*prev_on_ground,
);
});
prev_position.0 = position;
}
if on_ground != prev_on_ground.0 {
prev_on_ground.0 = on_ground;
}
}
Ok(())
}
/// Sends [SendEntityMetadata](protocol::packets::server::play::SendEntityMetadata) packet for when an entity is sneaking.
fn send_entity_sneak_metadata(game: &mut Game, server: &mut Server) -> SysResult {
for (_, (&position, &SneakEvent { is_sneaking }, is_sprinting, &network_id)) in game
.ecs
.query::<(&Position, &SneakEvent, &Sprinting, &NetworkId)>()
.iter()
{
let mut metadata = EntityMetadata::entity_base();
let mut bit_mask = EntityBitMask::empty();
// The Entity can sneak and sprint at the same time, what happens is that when it stops sneaking you immediately start running again.
bit_mask.set(EntityBitMask::CROUCHED, is_sneaking);
bit_mask.set(EntityBitMask::SPRINTING, is_sprinting.0);
metadata.set(META_INDEX_ENTITY_BITMASK, bit_mask.bits());
if is_sneaking {
metadata.set(META_INDEX_POSE, Pose::Sneaking);
} else {
metadata.set(META_INDEX_POSE, Pose::Standing);
}
server.broadcast_nearby_with(position, |client| {
client.send_entity_metadata(network_id, metadata.clone());
});
}
Ok(())
}
/// Sends [SendEntityMetadata](protocol::packets::server::play::SendEntityMetadata) packet for when an entity is sprinting.
fn send_entity_sprint_metadata(game: &mut Game, server: &mut Server) -> SysResult {
for (_, (&position, &SprintEvent { is_sprinting }, &network_id)) in game
.ecs
.query::<(&Position, &SprintEvent, &NetworkId)>()
.iter()
{
let mut metadata = EntityMetadata::entity_base();
let mut bit_mask = EntityBitMask::empty();
bit_mask.set(EntityBitMask::SPRINTING, is_sprinting);
metadata.set(META_INDEX_ENTITY_BITMASK, bit_mask.bits());
server.broadcast_nearby_with(position, |client| {
client.send_entity_metadata(network_id, metadata.clone());
});
}
Ok(())
}