mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
feat(inventory): implement lore methods for item stack (#3025)
This commit is contained in:
@@ -177,8 +177,33 @@ impl DataComponentImpl for ItemModelImpl {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct LoreImpl;
|
||||
pub struct LoreImpl {
|
||||
pub lines: Vec<TextComponent>,
|
||||
}
|
||||
impl LoreImpl {
|
||||
pub fn read_data(data: &NbtTag) -> Option<Self> {
|
||||
let NbtTag::List(lines) = data else {
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(Self {
|
||||
lines: lines
|
||||
.iter()
|
||||
.filter_map(NbtTag::extract_string)
|
||||
.map(|line| TextComponent::text(line.to_owned()))
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
impl DataComponentImpl for LoreImpl {
|
||||
fn write_data(&self) -> NbtTag {
|
||||
NbtTag::List(
|
||||
self.lines
|
||||
.iter()
|
||||
.map(|line| NbtTag::String(line.clone().get_text().into_boxed_str()))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
default_impl!(Lore);
|
||||
}
|
||||
|
||||
|
||||
@@ -539,6 +539,7 @@ pub fn read_data(id: DataComponent, data: &NbtTag) -> Option<Box<dyn DataCompone
|
||||
DataComponent::Fireworks => Some(FireworksImpl::read_data(data)?.to_dyn()),
|
||||
DataComponent::FireworkExplosion => Some(FireworkExplosionImpl::read_data(data)?.to_dyn()),
|
||||
DataComponent::CustomName => Some(CustomNameImpl::read_data(data)?.to_dyn()),
|
||||
DataComponent::Lore => Some(LoreImpl::read_data(data)?.to_dyn()),
|
||||
DataComponent::ItemName => Some(ItemNameImpl::read_data(data)?.to_dyn()),
|
||||
DataComponent::ItemModel => Some(ItemModelImpl::read_data(data)?.to_dyn()),
|
||||
DataComponent::Consumable => Some(ConsumableImpl::read_data(data)?.to_dyn()),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -206,6 +206,27 @@ impl ItemStack {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_lore(&mut self, lines: Vec<pumpkin_util::text::TextComponent>) {
|
||||
let lore = Some(Box::new(crate::data_component_impl::LoreImpl { lines }) as _);
|
||||
if let Some((_, component)) = self
|
||||
.patch
|
||||
.iter_mut()
|
||||
.find(|(id, _)| *id == DataComponent::Lore)
|
||||
{
|
||||
*component = lore;
|
||||
} else {
|
||||
self.patch.push((DataComponent::Lore, lore));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_lore(&mut self, line: pumpkin_util::text::TextComponent) {
|
||||
let mut lines = self
|
||||
.get_data_component::<crate::data_component_impl::LoreImpl>()
|
||||
.map_or_else(Vec::new, |lore| lore.lines.clone());
|
||||
lines.push(line);
|
||||
self.set_lore(lines);
|
||||
}
|
||||
|
||||
pub const EMPTY: &'static Self = &Self {
|
||||
item_count: 0,
|
||||
item: &Item::AIR,
|
||||
@@ -745,7 +766,7 @@ mod tests {
|
||||
use crate::data_component::DataComponent;
|
||||
use crate::data_component_impl::{
|
||||
CustomDataImpl, CustomNameImpl, DataComponentImpl, EnchantmentsImpl, ItemNameImpl,
|
||||
UnbreakableImpl,
|
||||
LoreImpl, UnbreakableImpl,
|
||||
};
|
||||
|
||||
/// Helper: creates a fresh Iron Sword (max_damage 250, damage 0).
|
||||
@@ -906,6 +927,20 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lore_can_be_set_and_appended() {
|
||||
let mut stack = ItemStack::new(1, &Item::WOODEN_AXE);
|
||||
stack.set_lore(vec![pumpkin_util::text::TextComponent::text("First line")]);
|
||||
stack.add_lore(pumpkin_util::text::TextComponent::text("Second line"));
|
||||
|
||||
let lore = stack
|
||||
.get_data_component::<LoreImpl>()
|
||||
.expect("lore component should be present");
|
||||
assert_eq!(lore.lines.len(), 2);
|
||||
assert_eq!(lore.lines[0].clone().get_text(), "First line");
|
||||
assert_eq!(lore.lines[1].clone().get_text(), "Second line");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_data_survives_item_stack_nbt_roundtrip() {
|
||||
let mut stack = ItemStack::new(1, &Item::WOODEN_AXE);
|
||||
|
||||
Reference in New Issue
Block a user