Crate shipyard[−][src]
Expand description
Shipyard is an Entity Component System focused on usability and speed.
Getting started
The user guide is a great place to learn all about Shipyard!
Here’s two examples to get an idea of what it provides:
use shipyard::prelude::*;
struct Health(f32);
struct Position { x: f32, y: f32 }
#[system(InAcid)]
fn run(pos: &Position, mut health: &mut Health) {
(&pos, &mut health).iter()
.filter(|(pos, _)| is_in_acid(pos))
.for_each(|(pos, mut health)| {
health.0 -= 1.0;
});
}
fn is_in_acid(pos: &Position) -> bool {
// it's wet season
true
}
let world = World::new();
{
let (mut entities, mut positions, mut healths) =
world.borrow::<(EntitiesMut, &mut Position, &mut Health)>();
entities.add_entity(
(&mut positions, &mut healths),
(Position { x: 0.0, y: 0.0 },
Health(1000.0))
);
}
world.run_system::<InAcid>();
Let’s make some pigs!
use shipyard::prelude::*;
struct Health(f32);
struct Fat(f32);
#[system(Reproduction)]
fn run(mut fat: &mut Fat, mut health: &mut Health, mut entities: &mut Entities) {
let count = (&health, &fat).iter().filter(|(health, fat)| health.0 > 40.0 && fat.0 > 20.0).count();
(0..count).for_each(|_| {
entities.add_entity((&mut health, &mut fat), (Health(100.0), Fat(0.0)));
});
}
#[system(Meal)]
fn run(mut fat: &mut Fat) {
(&mut fat).iter().into_chunk(8).ok().unwrap().for_each(|slice| {
for fat in slice {
fat.0 += 3.0;
}
});
}
#[system(Age)]
fn run(mut health: &mut Health, thread_pool: ThreadPool) {
use rayon::prelude::ParallelIterator;
thread_pool.install(|| {
(&mut health).par_iter().for_each(|health| {
health.0 -= 4.0;
});
});
}
let world = World::new();
world.run::<(EntitiesMut, &mut Health, &mut Fat), _, _>(|(mut entities, mut health, mut fat)| {
(0..100).for_each(|_| {
entities.add_entity(
(&mut health, &mut fat),
(Health(100.0), Fat(0.0))
);
})
});
world.add_workload::<(Meal, Age), _>("Life");
world.add_workload::<Reproduction, _>("Reproduction");
for day in 0..100 {
if day % 6 == 0 {
world.run_workload("Reproduction");
}
world.run_default();
}
world.run::<&Health, _, _>(|health| {
// we've got some new pigs
assert_eq!(health.len(), 900);
});
Features
- parallel (default) — adds parallel iterators and dispatch
- proc (default) — adds
system
proc macro - serde — adds (de)serialization support with serde
- non_send — add methods and types required to work with
!Send
components - non_sync — add methods and types required to work with
!Sync
components - std (default) — let shipyard use the standard library
Unsafe
This crate uses unsafe
both because sometimes there’s no way around it, and for performance gain.
Releases should have all invocation of unsafe
explained.
If you find places where a safe alternative is possible without repercussion (small ones are sometimes acceptable) feel free to open an issue or a PR.
Modules
Contains all error types.
Re-export types that aren’t needed in most use cases.
Structs
Contains all components present in the World.
Entities holds the EntityIds to all entities: living, removed and dead.
Type used to borrow Entities
mutably.
Type used to borrow the rayon::ThreadPool inside World
.
Type used to access the value of a unique storage.
Holds all components and keeps track of entities and what they own.