veloren_rtsim/rule/replenish_resources.rs
1use crate::{RtState, Rule, RuleError, event::OnTick};
2
3pub struct ReplenishResources;
4
5/// Take 1 hour to replenish resources entirely. Makes farming unviable, but
6/// probably still poorly balanced.
7// TODO: Different rates for different resources?
8// TODO: Non-renewable resources?
9pub const REPLENISH_TIME: f32 = 60.0 * 60.0;
10/// How many chunks should be replenished per tick?
11// TODO: It should be possible to optimise this be remembering the last
12// modification time for each chunk, then lazily projecting forward using a
13// closed-form solution to the replenishment to calculate resources in a lazy
14// manner.
15pub const REPLENISH_PER_TICK: usize = 8192;
16
17impl Rule for ReplenishResources {
18 fn start(rtstate: &mut RtState) -> Result<Self, RuleError> {
19 rtstate.bind::<Self, OnTick>(|ctx| {
20 let world_size = ctx.world.sim().get_size();
21 let mut data = ctx.state.data_mut();
22
23 // How much should be replenished for each chosen chunk to hit our target
24 // replenishment rate?
25 let replenish_amount = world_size.product() as f32
26 * ctx.event.dt
27 * (1.0 / REPLENISH_TIME / REPLENISH_PER_TICK as f32);
28
29 let chunks = data.nature.chunks.raw_mut();
30 // The number of times we need to replenish to cover the whole world
31 let group_count = chunks.len() / REPLENISH_PER_TICK + 1;
32 for chunk in chunks
33 .iter_mut()
34 .skip((ctx.event.tick as usize % group_count) * REPLENISH_PER_TICK)
35 .take(REPLENISH_PER_TICK)
36 {
37 for (_, res) in &mut chunk.res {
38 *res = (*res + replenish_amount).clamp(0.0, 1.0);
39 }
40 }
41 });
42
43 Ok(Self)
44 }
45}