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 mut chunk_res = data.nature.get_chunk_resources(key);
16 let get_resource_damage = |block: Block| {
17 block
18 .get_attr::<sprite::Damage>()
19 .ok()
20 .and_then(|damage| {
21 Some((damage.0, block.get_sprite()?.required_mine_damage()?))
22 })
23 .map_or(1.0, |(damage, required)| {
24 1.0 - (damage as f32 / required.max(1) as f32)
25 })
26 };
27
28 if let Some(res) = change.old.get_rtsim_resource() {
30 if chunk_state.max_res[res] > 0 {
31 chunk_res[res] = (chunk_res[res] * chunk_state.max_res[res] as f32
32 - get_resource_damage(change.old))
33 .round()
34 .max(0.0)
35 / chunk_state.max_res[res] as f32;
36 }
37 }
38 if let Some(res) = change.new.get_rtsim_resource() {
40 if chunk_state.max_res[res] > 0 {
41 chunk_res[res] = (chunk_res[res] * chunk_state.max_res[res] as f32
42 + get_resource_damage(change.new))
43 .round()
44 .max(0.0)
45 / chunk_state.max_res[res] as f32;
46 }
47 }
48
49 data.nature.set_chunk_resources(key, chunk_res);
50 }
51 }
52 });
53
54 Ok(Self)
55 }
56}