6 releases (3 breaking)
0.4.0 | Jul 25, 2023 |
---|---|
0.3.0 | Mar 21, 2023 |
0.2.3 | Mar 13, 2023 |
0.2.1 | Feb 16, 2023 |
0.1.0 | Feb 11, 2023 |
#1741 in Procedural macros
Used in 3 crates
(2 directly)
17KB
399 lines
About
pecs
is a plugin for Bevy that allows you to execute code asynchronously
by chaining multiple promises as part of Bevy's ecs
environment.
pecs
stands for Promise Entity Component System
.
Resources:
Compatibility:
bevy | pecs |
---|---|
0.13 | 0.6 |
0.12 | 0.5 |
0.11 | 0.4 |
0.10 | 0.3 |
0.9 | 0.2 |
Features
- Promise chaining with
then()
/then_repeat()
- State passing (
state
for promises is likeself
for items). - Complete type inference (the next promise knows the type of the previous result).
- Out-of-the-box timer, UI and HTTP promises via stateless
asyn
mod and statefulstate.asyn()
method. - Custom promise registration (add any asynchronous function you want!).
- System parameters fetching
(promise
asyn!
functions accept the same parameters as Bevy systems do). - Nested promises (with chaining, obviously).
- Combining promises with
any/all
for tuple/vec of promises via statelessPromise::any()
/Promise::all()
methods or statefulstate.any()
/state.all()
methods. - State mapping via
with(value)
/map(func)
(changes state type/value over chain calls). - Result mapping via
with_result(value)
/map_result(func)
(changes result type/value over chain calls).
Example
use bevy::prelude::*;
use pecs::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(PecsPlugin)
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands, time: Res<Time>) {
let start = time.elapsed_seconds();
commands
// create PromiseLike chainable commands
// with the current time as state
.promise(|| start)
// will be executed right after current stage
.then(asyn!(state => {
info!("Wait a second..");
state.asyn().timeout(1.0)
}))
// will be executed after in a second after previous call
.then(asyn!(state => {
info!("How large is is the Bevy main web page?");
state.asyn().http().get("https://bevyengine.org")
}))
// will be executed after request completes
.then(asyn!(state, result => {
match result {
Ok(response) => info!("It is {} bytes!", response.bytes.len()),
Err(err) => info!("Ahhh... something goes wrong: {err}")
}
state.pass()
}))
// will be executed right after the previous one
.then(asyn!(state, time: Res<Time> => {
let duration = time.elapsed_seconds() - state.value;
info!("It took {duration:0.2}s to do this job.");
info!("Exiting now");
asyn::app::exit()
}));
}
There is the output of the above example, pay some attention to time stamps:
18.667 INFO bevy_render::renderer: AdapterInfo { ... }
18.835 INFO simple: Wait a second..
19.842 INFO simple: How large is is the Bevy main web page?
19.924 INFO simple: It is 17759 bytes!
19.924 INFO simple: It tooks 1.09s to do this job.
19.924 INFO simple: Exiting now
Work in Progress
This crate is pretty young. API could and will change. The app may crash. Some promises could silently drop. Documentation is incomplete.
But. But. Examples work like a charm. And this fact gives us a lot of hope.
License
The pecs
is dual-licensed under either:
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
This means you can select the license you prefer! This dual-licensing approach is the de-facto standard in the Rust ecosystem and there are very good reasons to include both.
Dependencies
~2MB
~43K SLoC