use crate::rules::Version;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum WindowKind {
Chest {
rows: u8,
},
Generic3x3,
Hopper,
ShulkerBox,
Crafting,
Furnace,
BrewingStand,
Enchanting,
Anvil,
Beacon,
Merchant,
Horse {
slots: u8,
},
Grindstone,
Lectern,
Loom,
Smithing,
Cartography,
Stonecutter,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SlotKind {
Normal,
Armor(u8),
Offhand,
CraftResult,
Output,
Shulker,
Special,
}
impl WindowKind {
#[must_use]
pub fn from_v1_8(inventory_type: &str, slot_count: u8) -> Option<WindowKind> {
Some(match inventory_type {
"minecraft:container" => WindowKind::Chest {
rows: slot_count / 9,
},
"minecraft:villager" => WindowKind::Merchant,
"EntityHorse" => WindowKind::Horse { slots: slot_count },
_ if slot_count == 0 => match inventory_type {
"minecraft:crafting_table" => WindowKind::Crafting,
"minecraft:enchanting_table" => WindowKind::Enchanting,
"minecraft:anvil" => WindowKind::Anvil,
_ => return None,
},
"minecraft:hopper" => WindowKind::Hopper,
"minecraft:furnace" => WindowKind::Furnace,
"minecraft:brewing_stand" => WindowKind::BrewingStand,
"minecraft:beacon" => WindowKind::Beacon,
"minecraft:dispenser" | "minecraft:dropper" => WindowKind::Generic3x3,
_ => WindowKind::Chest {
rows: slot_count / 9,
},
})
}
#[must_use]
pub fn from_v1_16_5(menu_type: i32) -> Option<WindowKind> {
Some(match menu_type {
0..=5 => WindowKind::Chest {
rows: menu_type as u8 + 1,
},
6 => WindowKind::Generic3x3,
7 => WindowKind::Anvil,
8 => WindowKind::Beacon,
9 | 13 | 21 => WindowKind::Furnace, 10 => WindowKind::BrewingStand,
11 => WindowKind::Crafting,
12 => WindowKind::Enchanting,
14 => WindowKind::Grindstone,
15 => WindowKind::Hopper,
16 => WindowKind::Lectern,
17 => WindowKind::Loom,
18 => WindowKind::Merchant,
19 => WindowKind::ShulkerBox,
20 => WindowKind::Smithing,
22 => WindowKind::Cartography,
23 => WindowKind::Stonecutter,
_ => return None,
})
}
#[must_use]
pub fn container_len(self, version: Version) -> usize {
match self {
WindowKind::Chest { rows } => usize::from(rows) * 9,
WindowKind::Generic3x3 => 9,
WindowKind::Hopper => 5,
WindowKind::ShulkerBox => 27,
WindowKind::Crafting => 10,
WindowKind::Furnace => 3,
WindowKind::BrewingStand => match version {
Version::V1_8 => 4,
Version::V1_16_5 => 5,
},
WindowKind::Enchanting => 2,
WindowKind::Anvil => 3,
WindowKind::Beacon => 1,
WindowKind::Merchant => 3,
WindowKind::Horse { slots } => usize::from(slots),
WindowKind::Grindstone => 3,
WindowKind::Lectern => 1,
WindowKind::Loom => 4,
WindowKind::Smithing => 3,
WindowKind::Cartography => 3,
WindowKind::Stonecutter => 2,
}
}
#[must_use]
pub fn has_player_inventory(self) -> bool {
self != WindowKind::Lectern
}
#[must_use]
pub fn slot_kind(self, i: usize) -> SlotKind {
match self {
WindowKind::Chest { .. } | WindowKind::Generic3x3 | WindowKind::Hopper => {
SlotKind::Normal
}
WindowKind::ShulkerBox => SlotKind::Shulker,
WindowKind::Crafting => {
if i == 0 {
SlotKind::CraftResult
} else {
SlotKind::Normal
}
}
WindowKind::Furnace => match i {
0 => SlotKind::Normal,
1 => SlotKind::Special,
_ => SlotKind::Output,
},
WindowKind::Horse { .. } => {
if i < 2 {
SlotKind::Special
} else {
SlotKind::Normal
}
}
_ => SlotKind::Special,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn v1_8_types() {
assert_eq!(
WindowKind::from_v1_8("minecraft:chest", 54),
Some(WindowKind::Chest { rows: 6 })
);
assert_eq!(
WindowKind::from_v1_8("minecraft:container", 27),
Some(WindowKind::Chest { rows: 3 })
);
assert_eq!(
WindowKind::from_v1_8("plugin:whatever", 10),
Some(WindowKind::Chest { rows: 1 })
);
assert_eq!(
WindowKind::from_v1_8("minecraft:crafting_table", 0),
Some(WindowKind::Crafting)
);
assert_eq!(WindowKind::from_v1_8("minecraft:unknown", 0), None);
assert_eq!(
WindowKind::from_v1_8("minecraft:dropper", 9),
Some(WindowKind::Generic3x3)
);
assert_eq!(
WindowKind::from_v1_8("minecraft:brewing_stand", 4)
.unwrap()
.container_len(Version::V1_8),
4
);
}
#[test]
fn v1_16_types() {
assert_eq!(
WindowKind::from_v1_16_5(2),
Some(WindowKind::Chest { rows: 3 })
);
assert_eq!(WindowKind::from_v1_16_5(21), Some(WindowKind::Furnace));
assert_eq!(WindowKind::from_v1_16_5(24), None);
assert_eq!(WindowKind::from_v1_16_5(-1), None);
assert_eq!(WindowKind::BrewingStand.container_len(Version::V1_16_5), 5);
assert!(!WindowKind::Lectern.has_player_inventory());
}
}