Crates.io | bevy_mod_static_inventory |
lib.rs | bevy_mod_static_inventory |
version | 0.1.0 |
source | src |
created_at | 2023-09-12 22:15:17.894748 |
updated_at | 2023-09-12 22:15:17.894748 |
description | Static inventory for Bevy |
homepage | |
repository | https://github.com/SDesya74/bevy_mod_static_inventory |
max_upload_size | |
id | 971038 |
size | 126,701 |
Proof of concept of static inventory for Bevy. A static inventory means that each item type is a struct
(or enum
) with a specific set of traits. The advantages of this approach are excellent editor support and validity checking of some actions at compile time, e.g. you can't put sticks and apples in the same item stack.
It also opens up possibilities for partial support for inventory requests in ECS. For example, it is possible to call the system only for entities that have an apple in their inventory using Bevy's query filters.
This also allows you to add parameters to each individual item, such as color or durability for tools.
The current (not for long, I hope) drawbacks of this method, however, is the inability to create items in runtime.
cargo add bevy_mod_static_inventory
use std::{any::TypeId, time::Duration};
use bevy::{app::ScheduleRunnerPlugin, prelude::*};
use bevy_mod_static_inventory::{HasInInventory, Inventory, Item, Key};
fn main() {
App::new()
.add_plugins(
MinimalPlugins.set(ScheduleRunnerPlugin::run_loop(Duration::from_secs_f64(1.0))),
)
.add_systems(Startup, setup)
.add_systems(
Update,
(log_when_apple_in_inventory, log_when_stick_in_hand_slot),
)
.run();
}
pub struct HandSlot;
// TODO: Create derive macro
impl From<HandSlot> for Key {
fn from(_: HandSlot) -> Self {
Key::Type(TypeId::of::<HandSlot>())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Apple;
// TODO: Create derive macro
impl Item for Apple {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Stick;
impl Item for Stick {}
fn setup(mut commands: Commands) {
let mut inv = Inventory::new().with_slot_count(4);
inv.add(Apple).unwrap(); // add 1 apple
inv.add((Apple, 2)).unwrap(); // add 2 apples
inv.add((2, Apple)).unwrap(); // you also can swap count and item
commands.spawn(inv);
println!("Spawned entity with apples in inventory");
let mut inv = Inventory::new().with_custom_slot(HandSlot);
inv.insert(HandSlot, Stick).unwrap();
commands.spawn(inv);
println!("Spawned entity with apples in inventory");
}
fn log_when_apple_in_inventory(entities_with_apples: Query<DebugName, HasInInventory<Apple>>) {
for e in entities_with_apples.iter() {
println!("{:?} has Apple in inventory", e);
}
}
fn log_when_stick_in_hand_slot(
entities_with_apples: Query<DebugName, HasInInventory<Stick, HandSlot>>,
) {
for e in entities_with_apples.iter() {
println!("{:?} has Stick in hand slot", e);
}
}
Item
and Key
for custom slotsTypeId
in all places as it is unstable between buildsArmorSlot
containing Head
, Body
, Legs
variants)Item
as supertrait (now it is possible only in runtime with intertrait
and linkme
)