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