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