veloren_server/rtsim/rule/
deplete_resources.rs

1use 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                    // Remove resources
29                    if let Some(res) = change.old.get_rtsim_resource()
30                        && chunk_state.max_res[res] > 0
31                    {
32                        chunk_res[res] = ((chunk_res[res] * chunk_state.max_res[res] as f32
33                            - get_resource_damage(change.old))
34                            / chunk_state.max_res[res] as f32)
35                            .clamp(0.0, 1.0);
36                    }
37                    // Replenish resources
38                    if let Some(res) = change.new.get_rtsim_resource()
39                        && chunk_state.max_res[res] > 0
40                    {
41                        chunk_res[res] = ((chunk_res[res] * chunk_state.max_res[res] as f32
42                            + get_resource_damage(change.new))
43                            / chunk_state.max_res[res] as f32)
44                            .clamp(0.0, 1.0);
45                    }
46
47                    data.nature.set_chunk_resources(key, chunk_res);
48                }
49            }
50        });
51
52        Ok(Self)
53    }
54}