Shipyard is an Entity Component System crate. ECS is a pattern mostly used in games but not only. It fits really well with Rust, allowing easy composition and lifetime management.
What's new
-
User guide
Learning to use a crate with the documentation can be hard. There's now a guide to explain what can be done with Shipyard and how. - No need to register components anymore
Components had to be registered before accessing them by usingWorld::new
orWorld::register
.
Storages are now automatically created when they are first accessed. -
!Send
and!Sync
components
All components had to beSend + Sync
, this is a strict limitation to make sure storages can use parallel features.
With 0.3!Send
and!Sync
types can be stored and accessed while still following Rust's rules. These rules limit threading for these types but doesn't always prevent it. -
Unique
components
When we only need a single instance of a component, keeping an id around to access it can be annoying. AUnique
component won't be attached to any entity but will have the storage all for itself. - Components sorting
-
no_std
support - And more
Small Example
use shipyard::prelude::*;
struct Health(f32);
struct Position {
x: f32,
y: f32,
}
#[system(Populate)]
fn run(mut entities: &mut Entities, mut positions: &mut Position, mut healths: &mut Health) {
entities.add_entity(
(&mut positions, &mut healths),
(Position { x: 0.0, y: 0.0 }, Health(1000.0)),
);
}
#[system(InAcid)]
fn run(pos: &Position, mut health: &mut Health) {
(&pos, &mut health)
.iter()
.filter(|(pos, _)| is_in_acid(pos))
.for_each(|(_, mut health)| {
health.0 -= 1.0;
});
}
fn is_in_acid(pos: &Position) -> bool {
// it's wet season
true
}
fn main() {
let world = World::new();
world.run_system::<Populate>();
world.run_system::<InAcid>();
}
Lastly, I want to thank @dakom and @eldyer for all their help and support!