use crate::context::UnlockReason;
use crate::recipes::{Recipe, RecipeId};
use basalt_types::Slot;
#[derive(Debug, Clone)]
pub struct CraftingGridChangedEvent {
pub grid: [Option<i32>; 9],
pub grid_size: u8,
}
crate::game_event!(CraftingGridChangedEvent);
#[derive(Debug, Clone)]
pub struct CraftingRecipeMatchedEvent {
pub grid: [Option<i32>; 9],
pub grid_size: u8,
pub result: Slot,
}
crate::game_event!(CraftingRecipeMatchedEvent);
#[derive(Debug, Clone)]
pub struct CraftingRecipeClearedEvent {
pub grid_size: u8,
}
crate::game_event!(CraftingRecipeClearedEvent);
#[derive(Debug, Clone)]
pub struct CraftingPreCraftEvent {
pub result: Slot,
pub is_shift_click: bool,
pub cancelled: bool,
}
crate::game_cancellable_event!(CraftingPreCraftEvent);
#[derive(Debug, Clone)]
pub struct CraftingCraftedEvent {
pub consumed: [Slot; 9],
pub produced: Slot,
}
crate::game_event!(CraftingCraftedEvent);
#[derive(Debug, Clone)]
pub struct CraftingShiftClickBatchEvent {
pub result: Slot,
pub max_count: u32,
pub cancelled: bool,
}
crate::game_cancellable_event!(CraftingShiftClickBatchEvent);
#[derive(Debug, Clone)]
pub struct RecipeRegisterEvent {
pub recipe: Recipe,
pub cancelled: bool,
}
crate::game_cancellable_event!(RecipeRegisterEvent);
#[derive(Debug, Clone)]
pub struct RecipeRegisteredEvent {
pub recipe_id: RecipeId,
}
crate::game_event!(RecipeRegisteredEvent);
#[derive(Debug, Clone)]
pub struct RecipeUnregisteredEvent {
pub recipe_id: RecipeId,
}
crate::game_event!(RecipeUnregisteredEvent);
#[derive(Debug, Clone)]
pub struct RecipeUnlockedEvent {
pub recipe_id: RecipeId,
pub reason: UnlockReason,
}
crate::game_event!(RecipeUnlockedEvent);
#[derive(Debug, Clone)]
pub struct RecipeLockedEvent {
pub recipe_id: RecipeId,
}
crate::game_event!(RecipeLockedEvent);
#[derive(Debug, Clone)]
pub struct RecipeBookFillRequestEvent {
pub recipe_id: RecipeId,
pub make_all: bool,
pub cancelled: bool,
}
crate::game_cancellable_event!(RecipeBookFillRequestEvent);
#[derive(Debug, Clone)]
pub struct RecipeBookFilledEvent {
pub recipe_id: RecipeId,
pub make_all: bool,
}
crate::game_event!(RecipeBookFilledEvent);
#[cfg(test)]
mod tests {
use crate::events::{BusKind, Event, EventRouting};
use crate::recipes::OwnedShapedRecipe;
use super::*;
fn empty_grid() -> [Option<i32>; 9] {
[None; 9]
}
fn empty_slots() -> [Slot; 9] {
std::array::from_fn(|_| Slot::empty())
}
#[test]
fn grid_changed_not_cancellable() {
let mut event = CraftingGridChangedEvent {
grid: empty_grid(),
grid_size: 3,
};
event.cancel();
assert!(!event.is_cancelled());
assert_eq!(CraftingGridChangedEvent::BUS, BusKind::Game);
}
#[test]
fn recipe_matched_carries_mutable_result() {
let mut event = CraftingRecipeMatchedEvent {
grid: empty_grid(),
grid_size: 3,
result: Slot::new(1, 4),
};
event.result = Slot::empty();
assert!(event.result.item_id.is_none());
event.cancel();
assert!(!event.is_cancelled());
assert_eq!(CraftingRecipeMatchedEvent::BUS, BusKind::Game);
}
#[test]
fn recipe_cleared_not_cancellable() {
let mut event = CraftingRecipeClearedEvent { grid_size: 2 };
event.cancel();
assert!(!event.is_cancelled());
assert_eq!(CraftingRecipeClearedEvent::BUS, BusKind::Game);
}
#[test]
fn pre_craft_cancellation() {
let mut event = CraftingPreCraftEvent {
result: Slot::new(280, 4),
is_shift_click: false,
cancelled: false,
};
assert!(!event.is_cancelled());
event.cancel();
assert!(event.is_cancelled());
assert_eq!(CraftingPreCraftEvent::BUS, BusKind::Game);
}
#[test]
fn crafted_carries_consumed_and_produced() {
let mut consumed = empty_slots();
consumed[0] = Slot::new(17, 1);
let event = CraftingCraftedEvent {
consumed,
produced: Slot::new(280, 4),
};
assert_eq!(event.consumed[0].item_id, Some(17));
assert_eq!(event.produced.item_count, 4);
assert_eq!(CraftingCraftedEvent::BUS, BusKind::Game);
}
#[test]
fn shift_click_batch_cap_and_cancel() {
let mut event = CraftingShiftClickBatchEvent {
result: Slot::new(280, 4),
max_count: u32::MAX,
cancelled: false,
};
event.max_count = 2;
assert_eq!(event.max_count, 2);
event.cancel();
assert!(event.is_cancelled());
assert_eq!(CraftingShiftClickBatchEvent::BUS, BusKind::Game);
}
fn sample_recipe(path: &str) -> Recipe {
Recipe::Shaped(OwnedShapedRecipe {
id: RecipeId::new("plugin", path),
width: 1,
height: 1,
pattern: vec![Some(1)],
result_id: 42,
result_count: 1,
})
}
#[test]
fn recipe_register_cancellation() {
let mut event = RecipeRegisterEvent {
recipe: sample_recipe("magic_sword"),
cancelled: false,
};
assert!(!event.is_cancelled());
event.cancel();
assert!(event.is_cancelled());
assert_eq!(RecipeRegisterEvent::BUS, BusKind::Game);
}
#[test]
fn recipe_registered_carries_id() {
let mut event = RecipeRegisteredEvent {
recipe_id: RecipeId::vanilla("crafting_table"),
};
event.cancel();
assert!(!event.is_cancelled());
assert_eq!(event.recipe_id.namespace, "minecraft");
assert_eq!(RecipeRegisteredEvent::BUS, BusKind::Game);
}
#[test]
fn recipe_unregistered_carries_id() {
let mut event = RecipeUnregisteredEvent {
recipe_id: RecipeId::new("plugin", "obsolete"),
};
event.cancel();
assert!(!event.is_cancelled());
assert_eq!(event.recipe_id.path, "obsolete");
assert_eq!(RecipeUnregisteredEvent::BUS, BusKind::Game);
}
#[test]
fn recipe_unlocked_carries_id_and_reason() {
let mut event = RecipeUnlockedEvent {
recipe_id: RecipeId::vanilla("oak_planks"),
reason: UnlockReason::AutoDiscovered,
};
event.cancel();
assert!(!event.is_cancelled());
assert_eq!(event.reason, UnlockReason::AutoDiscovered);
assert_eq!(RecipeUnlockedEvent::BUS, BusKind::Game);
}
#[test]
fn recipe_locked_carries_id() {
let mut event = RecipeLockedEvent {
recipe_id: RecipeId::new("plugin", "expired"),
};
event.cancel();
assert!(!event.is_cancelled());
assert_eq!(event.recipe_id.path, "expired");
assert_eq!(RecipeLockedEvent::BUS, BusKind::Game);
}
#[test]
fn fill_request_cancellation() {
let mut event = RecipeBookFillRequestEvent {
recipe_id: RecipeId::vanilla("oak_planks"),
make_all: false,
cancelled: false,
};
assert!(!event.is_cancelled());
event.cancel();
assert!(event.is_cancelled());
assert_eq!(RecipeBookFillRequestEvent::BUS, BusKind::Game);
}
#[test]
fn fill_request_carries_make_all() {
let event = RecipeBookFillRequestEvent {
recipe_id: RecipeId::vanilla("oak_planks"),
make_all: true,
cancelled: false,
};
assert!(event.make_all);
}
#[test]
fn filled_carries_id_and_make_all() {
let mut event = RecipeBookFilledEvent {
recipe_id: RecipeId::vanilla("crafting_table"),
make_all: false,
};
event.cancel();
assert!(!event.is_cancelled());
assert_eq!(RecipeBookFilledEvent::BUS, BusKind::Game);
}
}