Skip to content

Commit 316f490

Browse files
committed
Block breaking speed calculation
1 parent 3e5d7e8 commit 316f490

File tree

3 files changed

+65
-10
lines changed

3 files changed

+65
-10
lines changed

feather/common/src/block_break.rs

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use base::{ItemStack, ValidBlockPosition};
22
use ecs::{EntityBuilder, SysResult, SystemExecutor};
3+
use libcraft_items::EnchantmentKind;
34
use quill_common::entity_init::EntityInit;
45

56
pub struct DestroyStateChange(pub ValidBlockPosition, pub u8);
@@ -39,17 +40,63 @@ impl ActiveBlockBreaker {
3940
Ok(())
4041
}
4142
pub fn new_player(
42-
_world: &mut World,
43+
world: &mut World,
4344
block_pos: ValidBlockPosition,
44-
_mainhand: Option<&ItemStack>,
45-
_offhand: Option<&ItemStack>,
45+
main_hand: Option<&ItemStack>,
4646
) -> Option<Self> {
47-
// TODO
47+
let block = world.block_at(block_pos)?.kind();
48+
if !block.diggable() {
49+
return None;
50+
}
51+
let harvestable = match (block.harvest_tools(), main_hand) {
52+
(None, None | Some(_)) => true,
53+
(Some(_), None) => false,
54+
(Some(tools), Some(tool)) => tools.contains(&tool.item()),
55+
};
56+
let dig_multiplier = block
57+
.dig_multipliers()
58+
.iter()
59+
.find_map(|(item, speed)| {
60+
main_hand
61+
.map(|e| {
62+
if e.item() == *item {
63+
Some(*speed)
64+
} else {
65+
None
66+
}
67+
})
68+
.flatten()
69+
})
70+
.unwrap_or(1.0);
71+
let effi_level = main_hand
72+
.map(ItemStack::metadata)
73+
.flatten()
74+
.map(|meta| {
75+
meta.enchantments().iter().find_map(|ench| {
76+
if ench.kind() == EnchantmentKind::Efficiency {
77+
Some(ench.level())
78+
} else {
79+
None
80+
}
81+
})
82+
})
83+
.flatten();
84+
let effi_speed = effi_level.map(|level| level * level + 1).unwrap_or(0) as f32;
85+
let damage = if harvestable {
86+
(dig_multiplier + effi_speed) / block.hardness() / 30.0
87+
} else {
88+
1.0 / block.hardness() / 100.0
89+
};
90+
let ticks = if damage > 1.0 {
91+
0
92+
} else {
93+
(1.0 / damage).ceil() as u32 - 4
94+
};
4895
Some(Self {
4996
position: block_pos,
5097
drop_item: true,
51-
total_ticks: 20,
52-
ticks_remaining: 20,
98+
total_ticks: ticks,
99+
ticks_remaining: ticks,
53100
})
54101
}
55102
pub fn destroy_stage(&self) -> u8 {

feather/server/src/packet_handlers/interaction.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,12 @@ pub fn handle_player_digging(
131131
let mut breaker = game.ecs.get_mut::<BlockBreaker>(player)?;
132132
let window = game.ecs.get::<Window>(player)?;
133133
let hotbar_slot = game.ecs.get::<HotbarSlot>(player)?.get();
134-
let main = window.item(SLOT_HOTBAR_OFFSET + hotbar_slot)?;
135-
let offh = window.item(SLOT_OFFHAND)?;
134+
let main_hand = window.item(SLOT_HOTBAR_OFFSET + hotbar_slot)?;
136135
let _ = breaker.insert(
137136
ActiveBlockBreaker::new_player(
138137
&mut game.world,
139138
packet.position,
140-
main.item_stack(),
141-
offh.item_stack(),
139+
main_hand.item_stack(),
142140
)
143141
.unwrap(),
144142
);

libcraft/items/src/item_stack.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,10 @@ impl ItemStack {
324324
pub fn stack_size(&self) -> u32 {
325325
self.item.stack_size()
326326
}
327+
328+
pub fn metadata(&self) -> Option<&ItemStackMeta> {
329+
self.meta.as_ref()
330+
}
327331
}
328332

329333
/// An error type that may be returned when performing
@@ -355,6 +359,12 @@ impl ItemStackMeta {
355359
enchantments: vec![],
356360
}
357361
}
362+
pub fn enchantments(&self) -> &[Enchantment] {
363+
&self.enchantments
364+
}
365+
pub fn enchantments_mut(&mut self) -> &mut Vec<Enchantment> {
366+
&mut self.enchantments
367+
}
358368
}
359369

360370
pub struct ItemStackBuilder {

0 commit comments

Comments
 (0)