use std::collections::{
HashMap,
HashSet,
};
use bevy::prelude::*;
#[cfg(feature = "serde")]
use serde::{
Deserialize,
Serialize,
};
use crate::textdisplay::{
Message,
TextDisplay,
};
pub struct InventoryPlugin;
#[rustfmt::skip]
impl Plugin for InventoryPlugin {
fn build(&self, app: &mut App) {
app
.insert_resource(DraggingItem::default())
.insert_resource(Inventory::default())
.insert_resource(Recipes::default())
.add_system(handle_combine);
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Resource, Debug, Default)]
pub struct Inventory {
pub items: HashSet<Item>,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Item {
name: String,
}
impl Item {
pub fn new(name: &str) -> Self {
Self {
name: name.to_owned(),
}
}
pub fn as_str(&self) -> &str {
&self.name
}
}
impl From<&str> for Item {
fn from(name: &str) -> Self {
Item::new(name)
}
}
impl From<String> for Item {
fn from(name: String) -> Self {
Item::new(&name)
}
}
#[derive(Resource, Default)]
pub struct DraggingItem {
pub src: Option<Item>,
pub dst: Option<Item>,
}
impl DraggingItem {
pub fn is_dragging(&self) -> bool {
self.src.is_some() || self.dst.is_some()
}
}
#[derive(Resource, Default)]
pub struct Recipes {
map: HashMap<(Item, Item), Item>,
}
impl Recipes {
pub fn insert(&mut self, a: &str, b: &str, result: &str) {
self.map.insert((a.into(), b.into()), result.into());
self.map.insert((b.into(), a.into()), result.into());
}
pub fn get(&self, src: &Item, dst: &Item) -> Option<&Item> {
self.map.get(&(src.clone(), dst.clone()))
}
}
#[allow(clippy::needless_pass_by_value)]
fn handle_combine(
input: Res<Input<MouseButton>>,
mut display: TextDisplay,
mut inventory: ResMut<Inventory>,
recipes: Res<Recipes>,
dragging: Res<DraggingItem>,
) {
if input.just_released(MouseButton::Left) {
if let (Some(src), Some(dst)) = (&dragging.src, &dragging.dst) {
if let Some(result) = recipes.get(src, dst) {
inventory.items.remove(src);
inventory.items.remove(dst);
inventory.items.insert(result.clone());
let src = src.clone();
let dst = dst.clone();
let result = result.clone();
display.show(Message::ItemCombine { src, dst, result });
} else {
display.show(Message::InvalidItemCombination);
}
}
}
}