Skip to content

Commit bb33f00

Browse files
authored
Handle held item change packet (feather-rs#361)
This adds basic handling to held item change packets. Fixes feather-rs#355. This can be used in the future to add "get item in hand" support.
1 parent b9249fe commit bb33f00

4 files changed

Lines changed: 79 additions & 9 deletions

File tree

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,36 @@
1+
use anyhow::bail;
12
use base::EntityKind;
2-
use ecs::EntityBuilder;
3+
use ecs::{EntityBuilder, SysResult};
34
use quill_common::entities::Player;
45

56
pub fn build_default(builder: &mut EntityBuilder) {
67
super::build_default(builder);
78
builder.add(Player).add(EntityKind::Player);
89
}
10+
11+
/// The hotbar slot a player's cursor is currently on
12+
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
13+
pub struct HotbarSlot(usize);
14+
15+
impl HotbarSlot {
16+
pub fn new(id: usize) -> Self {
17+
Self(id)
18+
}
19+
20+
pub fn default() -> Self {
21+
Self(0)
22+
}
23+
24+
pub fn get(&self) -> usize {
25+
self.0
26+
}
27+
28+
pub fn set(&mut self, id: usize) -> SysResult {
29+
if id > 8 {
30+
bail!("invalid hotbar slot id");
31+
}
32+
33+
self.0 = id;
34+
Ok(())
35+
}
36+
}

feather/server/src/packet_handlers.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use base::{Position, Text};
22
use common::{chat::ChatKind, Game};
33
use ecs::{Entity, EntityRef, SysResult};
4-
use interaction::{handle_interact_entity, handle_player_block_placement, handle_player_digging};
4+
use interaction::{
5+
handle_held_item_change, handle_interact_entity, handle_player_block_placement,
6+
handle_player_digging,
7+
};
58
use protocol::{
69
packets::{
710
client,
@@ -56,6 +59,7 @@ pub fn handle_packet(
5659
handle_player_block_placement(game, server, packet, player_id)
5760
}
5861

62+
ClientPlayPacket::HeldItemChange(packet) => handle_held_item_change(player, packet),
5963
ClientPlayPacket::InteractEntity(packet) => {
6064
handle_interact_entity(game, server, packet, player_id)
6165
}
@@ -89,7 +93,6 @@ pub fn handle_packet(
8993
| ClientPlayPacket::AdvancementTab(_)
9094
| ClientPlayPacket::SelectTrade(_)
9195
| ClientPlayPacket::SetBeaconEffect(_)
92-
| ClientPlayPacket::HeldItemChange(_)
9396
| ClientPlayPacket::UpdateCommandBlock(_)
9497
| ClientPlayPacket::UpdateCommandBlockMinecart(_)
9598
| ClientPlayPacket::UpdateJigsawBlock(_)

feather/server/src/packet_handlers/interaction.rs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
use crate::{ClientId, NetworkId, Server};
2+
use common::entities::player::HotbarSlot;
3+
use common::events::InteractEntityEvent;
24
use common::Game;
35
use common::{
4-
events::{BlockInteractEvent, BlockPlacementEvent, InteractEntityEvent},
6+
events::{BlockInteractEvent, BlockPlacementEvent},
57
interactable::InteractableRegistry,
68
};
7-
use ecs::{Entity, SysResult};
8-
use libcraft_core::{BlockFace as LibcraftBlockFace, Hand, InteractionType, Vec3f};
9+
use ecs::{Entity, EntityRef, SysResult};
10+
use libcraft_core::{BlockFace as LibcraftBlockFace, Hand};
11+
use libcraft_core::{InteractionType, Vec3f};
912
use protocol::packets::client::{
10-
BlockFace, InteractEntity, InteractEntityKind, PlayerBlockPlacement, PlayerDigging,
11-
PlayerDiggingStatus,
13+
BlockFace, HeldItemChange, InteractEntity, InteractEntityKind, PlayerBlockPlacement,
14+
PlayerDigging, PlayerDiggingStatus,
1215
};
1316

1417
/// Handles the player block placement packet. Currently just removes the block client side for the player.
@@ -193,3 +196,37 @@ pub fn handle_interact_entity(
193196

194197
Ok(())
195198
}
199+
200+
pub fn handle_held_item_change(player: EntityRef, packet: HeldItemChange) -> SysResult {
201+
let new_id = packet.slot as usize;
202+
let mut slot = player.get_mut::<HotbarSlot>()?;
203+
204+
log::trace!("Got player slot change from {} to {}", slot.get(), new_id);
205+
206+
slot.set(new_id)?;
207+
Ok(())
208+
}
209+
210+
#[cfg(test)]
211+
mod tests {
212+
use common::Game;
213+
use protocol::packets::client::HeldItemChange;
214+
215+
use super::*;
216+
217+
#[test]
218+
fn held_item_change() {
219+
let mut game = Game::new();
220+
let entity = game.ecs.spawn((HotbarSlot::new(0),));
221+
let player = game.ecs.entity(entity).unwrap();
222+
223+
let packet = HeldItemChange { slot: 8 };
224+
225+
handle_held_item_change(player, packet).unwrap();
226+
227+
assert_eq!(
228+
*game.ecs.get::<HotbarSlot>(entity).unwrap(),
229+
HotbarSlot::new(8)
230+
);
231+
}
232+
}

feather/server/src/systems/player_join.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use base::{Inventory, Position, Text};
22
use common::{
33
chat::{ChatKind, ChatPreference},
4+
entities::player::HotbarSlot,
45
view::View,
56
window::BackingWindow,
67
ChatBox, Game, Window,
@@ -50,7 +51,8 @@ fn accept_new_player(game: &mut Game, server: &mut Server, client_id: ClientId)
5051
.add(client.profile().to_vec())
5152
.add(ChatBox::new(ChatPreference::All))
5253
.add(inventory)
53-
.add(window);
54+
.add(window)
55+
.add(HotbarSlot::default());
5456

5557
game.spawn_entity(builder);
5658

0 commit comments

Comments
 (0)