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 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                    // Remove resources
30                    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                    // Replenish resources
39                    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}