Skip to content

Commit 7288a29

Browse files
authored
Entity sneak and sprint (#492)
* Add Pose Enum and change Const name for it. * Add client function to send `SendEntityMetadata` packet. * Add entity_sneak and entity_sprint systems for metadata. * don't call the function.
1 parent 567262c commit 7288a29

File tree

3 files changed

+96
-4
lines changed

3 files changed

+96
-4
lines changed

feather/base/src/metadata.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub const META_INDEX_IS_CUSTOM_NAME_VISIBLE: u8 = 3;
2020
pub const META_INDEX_IS_SILENT: u8 = 4;
2121
pub const META_INDEX_NO_GRAVITY: u8 = 5;
2222

23-
pub const META_INDEX_ITEM_SLOT: u8 = 6;
23+
pub const META_INDEX_POSE: u8 = 6;
2424

2525
pub const META_INDEX_FALLING_BLOCK_SPAWN_POSITION: u8 = 7;
2626

@@ -85,6 +85,30 @@ impl MetaEntry {
8585
}
8686
}
8787

88+
pub enum Pose {
89+
Standing,
90+
FallFlying,
91+
Sleeping,
92+
Swimming,
93+
SpinAttack,
94+
Sneaking,
95+
Dying,
96+
}
97+
98+
impl ToMetaEntry for Pose {
99+
fn to_meta_entry(&self) -> MetaEntry {
100+
MetaEntry::Pose(match self {
101+
Self::Standing => 0,
102+
Self::FallFlying => 1,
103+
Self::Sleeping => 2,
104+
Self::Swimming => 3,
105+
Self::SpinAttack => 4,
106+
Self::Sneaking => 5,
107+
Self::Dying => 6,
108+
})
109+
}
110+
}
111+
88112
pub trait ToMetaEntry {
89113
fn to_meta_entry(&self) -> MetaEntry;
90114
}

feather/server/src/client.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,16 @@ impl Client {
547547
});
548548
}
549549

550+
pub fn send_entity_metadata(&self, network_id: NetworkId, metadata: EntityMetadata) {
551+
if self.network_id == Some(network_id) {
552+
return;
553+
}
554+
self.send_packet(SendEntityMetadata {
555+
entity_id: network_id.0,
556+
entries: metadata,
557+
});
558+
}
559+
550560
pub fn send_abilities(&self, abilities: &base::anvil::player::PlayerAbilities) {
551561
let mut bitfield = 0;
552562
if *abilities.invulnerable {

feather/server/src/systems/entity.rs

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
11
//! Sends entity-related packets to clients.
22
//! Spawn packets, position updates, equipment, animations, etc.
33
4-
use base::Position;
4+
use base::{
5+
metadata::{EntityBitMask, Pose, META_INDEX_ENTITY_BITMASK, META_INDEX_POSE},
6+
EntityMetadata, Position,
7+
};
58
use common::Game;
69
use ecs::{SysResult, SystemExecutor};
7-
use quill_common::components::OnGround;
10+
use quill_common::{
11+
components::{OnGround, Sprinting},
12+
events::{SneakEvent, SprintEvent},
13+
};
814

915
use crate::{entities::PreviousPosition, NetworkId, Server};
1016

1117
mod spawn_packet;
1218

1319
pub fn register(game: &mut Game, systems: &mut SystemExecutor<Game>) {
1420
spawn_packet::register(game, systems);
15-
systems.group::<Server>().add_system(send_entity_movement);
21+
systems
22+
.group::<Server>()
23+
.add_system(send_entity_movement)
24+
.add_system(send_entity_sneak_metadata)
25+
.add_system(send_entity_sprint_metadata);
1626
}
1727

1828
/// Sends entity movement packets.
@@ -31,3 +41,51 @@ fn send_entity_movement(game: &mut Game, server: &mut Server) -> SysResult {
3141
}
3242
Ok(())
3343
}
44+
45+
/// Sends [SendEntityMetadata](protocol::packets::server::play::SendEntityMetadata) packet for when an entity is sneaking.
46+
fn send_entity_sneak_metadata(game: &mut Game, server: &mut Server) -> SysResult {
47+
for (_, (&position, &SneakEvent { is_sneaking }, is_sprinting, &network_id)) in game
48+
.ecs
49+
.query::<(&Position, &SneakEvent, &Sprinting, &NetworkId)>()
50+
.iter()
51+
{
52+
let mut metadata = EntityMetadata::entity_base();
53+
let mut bit_mask = EntityBitMask::empty();
54+
55+
// The Entity can sneak and sprint at the same time, what happens is that when it stops sneaking you immediately start running again.
56+
bit_mask.set(EntityBitMask::CROUCHED, is_sneaking);
57+
bit_mask.set(EntityBitMask::SPRINTING, is_sprinting.0);
58+
metadata.set(META_INDEX_ENTITY_BITMASK, bit_mask.bits());
59+
60+
if is_sneaking {
61+
metadata.set(META_INDEX_POSE, Pose::Sneaking);
62+
} else {
63+
metadata.set(META_INDEX_POSE, Pose::Standing);
64+
}
65+
66+
server.broadcast_nearby_with(position, |client| {
67+
client.send_entity_metadata(network_id, metadata.clone());
68+
});
69+
}
70+
Ok(())
71+
}
72+
73+
/// Sends [SendEntityMetadata](protocol::packets::server::play::SendEntityMetadata) packet for when an entity is sprinting.
74+
fn send_entity_sprint_metadata(game: &mut Game, server: &mut Server) -> SysResult {
75+
for (_, (&position, &SprintEvent { is_sprinting }, &network_id)) in game
76+
.ecs
77+
.query::<(&Position, &SprintEvent, &NetworkId)>()
78+
.iter()
79+
{
80+
let mut metadata = EntityMetadata::entity_base();
81+
let mut bit_mask = EntityBitMask::empty();
82+
83+
bit_mask.set(EntityBitMask::SPRINTING, is_sprinting);
84+
metadata.set(META_INDEX_ENTITY_BITMASK, bit_mask.bits());
85+
86+
server.broadcast_nearby_with(position, |client| {
87+
client.send_entity_metadata(network_id, metadata.clone());
88+
});
89+
}
90+
Ok(())
91+
}

0 commit comments

Comments
 (0)