screeps_async/
macros.rs

1//! Macros to make common workflows easier
2
3pub use screeps_async_macros::*;
4
5/// Run a block of code each tick, resolving the specified list of
6/// dependencies by calling `.resolve` each tick and exiting if
7/// any dependency can't be resolved.
8///
9/// Dependencies can be of any type, but must have a `.resolve` method
10/// that returns an [`Option`]
11///
12/// The resolved dependencies will be available within the code block
13/// under the same ident. EG an [`screeps::ObjectId<screeps::Creep>`] called `creep`
14/// will be resolved to a [`screeps::Creep`] also called `creep`
15///
16/// The code block must return an [`Option`]. If the code block returns [`None`],
17/// then execution will continue next tick. If the code block returns [`Some`],
18/// then looping will cease and `each_tick!` will return whatever the value returned by the code block
19///
20/// Returns [`Some`] if the inner block ever returned [`Some`]
21///
22/// # Errors
23///
24/// Returns [`None`] if any dependency ever fails to resolve
25///
26/// # Examples
27///
28/// ```
29/// use screeps::*;
30/// async fn harvest_forever(creep: ObjectId<Creep>, source: ObjectId<Source>) {
31///     screeps_async::each_tick!(creep, source, {
32///         let _ = creep.harvest(&source);
33///         None::<()> // do this forever
34///     }).await;
35/// }
36/// ```
37#[macro_export]
38macro_rules! each_tick {
39    ($($dep:ident),*, $body:block) => {
40        async move {
41            loop {
42                $(
43                    let $dep = $dep.resolve()?;
44                )*
45                let fut = async move $body;
46                if let Some(ret) = fut.await {
47                    return Some(ret);
48                }
49
50                ::screeps_async::time::yield_tick().await;
51            }
52        }
53    }
54}