azalea_protocol/packets/game/
c_merchant_offers.rs1use std::{
2 any::Any,
3 fmt::{self, Debug},
4 io::{self, Cursor, Write},
5};
6
7use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
8use azalea_inventory::{
9 DataComponentPatch, ItemStack, ItemStackData,
10 components::{self, DataComponentUnion},
11};
12use azalea_protocol_macros::ClientboundGamePacket;
13use azalea_registry::{DataComponentKind, Item};
14
15#[derive(Clone, Debug, AzBuf, ClientboundGamePacket)]
16pub struct ClientboundMerchantOffers {
17 #[var]
18 pub container_id: i32,
19 pub offers: Vec<MerchantOffer>,
20 #[var]
21 pub villager_level: u32,
22 #[var]
23 pub villager_xp: u32,
24 pub show_progress: bool,
25 pub can_restock: bool,
26}
27
28#[derive(Clone, Debug, AzBuf)]
29pub struct MerchantOffer {
30 pub base_cost_a: ItemCost,
31 pub result: ItemStack,
32 pub cost_b: Option<ItemCost>,
33 pub out_of_stock: bool,
34 pub uses: i32,
35 pub max_uses: i32,
36 pub xp: i32,
37 pub special_price_diff: i32,
38 pub price_multiplier: f32,
39 pub demand: i32,
40}
41
42#[derive(Clone, Debug, AzBuf)]
47pub struct ItemCost {
48 pub item: Item,
49 #[var]
50 pub count: i32,
51 pub components: DataComponentExactPredicate,
52}
53impl ItemCost {
54 pub fn into_item_stack(self) -> ItemStackData {
55 let mut component_patch = DataComponentPatch::default();
56 for component in self.components.expected {
57 unsafe {
58 component_patch.unchecked_insert_component(component.kind, Some(component.value));
59 }
60 }
61 ItemStackData {
65 kind: self.item,
66 count: self.count,
67 component_patch,
68 }
69 }
70}
71
72#[derive(Clone, Debug, AzBuf)]
78pub struct DataComponentExactPredicate {
79 pub expected: Vec<TypedDataComponent>,
80}
81
82pub struct TypedDataComponent {
83 kind: DataComponentKind,
84 value: DataComponentUnion,
85}
86impl TypedDataComponent {
87 pub fn kind(&self) -> &DataComponentKind {
88 &self.kind
89 }
90 pub fn value(&self) -> &DataComponentUnion {
91 &self.value
92 }
93 pub fn as_dyn(&self) -> &dyn components::EncodableDataComponent {
94 unsafe { self.value.as_kind(self.kind) }
97 }
98 pub fn get<T: components::DataComponentTrait>(&self) -> Option<&T> {
99 let component = self.as_dyn();
100 let component_any = component as &dyn Any;
101 component_any.downcast_ref::<T>()
102 }
103}
104impl AzaleaRead for TypedDataComponent {
105 fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
106 let kind = DataComponentKind::azalea_read(buf)?;
107 let value = DataComponentUnion::azalea_read_as(kind, buf)?;
108 Ok(Self { kind, value })
109 }
110}
111impl AzaleaWrite for TypedDataComponent {
112 fn azalea_write(&self, buf: &mut impl Write) -> io::Result<()> {
113 self.kind.azalea_write(buf)?;
114 unsafe { self.value.azalea_write_as(self.kind, buf) }
115 }
116}
117impl Debug for TypedDataComponent {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 f.debug_struct("TypedDataComponent")
120 .field("kind", &self.kind)
121 .finish()
122 }
123}
124impl Clone for TypedDataComponent {
125 fn clone(&self) -> Self {
126 Self {
127 kind: self.kind,
128 value: unsafe { self.value.clone_as(self.kind) },
129 }
130 }
131}