veloren_server/rtsim/rule/
deplete_resources.rs1use crate::rtsim::{ChunkStates, event::OnBlockChange};
2use common::terrain::{Block, CoordinateConversions, sprite};
3use rtsim::{RtState, Rule, RuleError};
4
5pub struct DepleteResources;
6
7impl Rule for DepleteResources {
8 fn start(rtstate: &mut RtState) -> Result<Self, RuleError> {
9 rtstate.bind::<Self, OnBlockChange>(|ctx| {
10 let chunk_states = ctx.state.resource::<ChunkStates>();
11 let mut data = ctx.state.data_mut();
12 for change in &ctx.event.changes {
13 let key = change.wpos.xy().wpos_to_cpos();
14 if let Some(Some(chunk_state)) = chunk_states.0.get(key)
15 && let Some(chunk_res) = data.nature.chunk_resources_mut(key)
16 {
17 let get_resource_damage = |block: Block| {
18 block
19 .get_attr::<sprite::Damage>()
20 .ok()
21 .and_then(|damage| {
22 Some((damage.0, block.get_sprite()?.required_mine_damage()?))
23 })
24 .map_or(1.0, |(damage, required)| {
25 1.0 - (damage as f32 / required.max(1) as f32)
26 })
27 };
28
29 if let Some(res) = change.old.get_rtsim_resource()
31 && chunk_state.max_res[res] > 0
32 {
33 chunk_res[res] = ((chunk_res[res] * chunk_state.max_res[res] as f32
34 - get_resource_damage(change.old))
35 / chunk_state.max_res[res] as f32)
36 .clamp(0.0, 1.0);
37 }
38 if let Some(res) = change.new.get_rtsim_resource()
40 && chunk_state.max_res[res] > 0
41 {
42 chunk_res[res] = ((chunk_res[res] * chunk_state.max_res[res] as f32
43 + get_resource_damage(change.new))
44 / chunk_state.max_res[res] as f32)
45 .clamp(0.0, 1.0);
46 }
47 }
48 }
49 });
50
51 Ok(Self)
52 }
53}