1 unstable release
0.1.0 | Sep 12, 2023 |
---|
#1155 in Game dev
33KB
524 lines
Static Inventory
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.
Installation
cargo add bevy_mod_static_inventory
Usage
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);
}
}
Progress
- Typed and boxed ItemStacks
- Numbered and custom slots
- Derive macros for defining
Item
andKey
for custom slots - Advanced query filters (added/removed item etc)
- Full documentation
- Support for dynamic item registering (for modding)
- Remove dependency on
TypeId
in all places as it is unstable between builds - Support for enum slots (e.g.
ArmorSlot
containingHead
,Body
,Legs
variants) - Support downcasting for more concrete traits, that have
Item
as supertrait (now it is possible only in runtime withintertrait
andlinkme
)
Dependencies
~21–30MB
~463K SLoC