diff --git a/azalea-chat/src/component.rs b/azalea-chat/src/component.rs index d301aba15..55fbd30dc 100755 --- a/azalea-chat/src/component.rs +++ b/azalea-chat/src/component.rs @@ -308,65 +308,89 @@ impl simdnbt::FromNbtTag for FormattedText { } else if let Some(translate) = compound.get("translate") { let translate = translate.string()?.into(); if let Some(with) = compound.get("with") { - let with = with.list()?.compounds()?; - let mut with_array = Vec::with_capacity(with.len()); - for item in with { - // if it's a string component with no styling and no siblings, just add - // a string to with_array otherwise add the - // component to the array - if let Some(primitive) = item.get("") { - // minecraft does this sometimes, for example - // for the /give system messages - match primitive { - simdnbt::borrow::NbtTag::Byte(b) => { - // interpreted as boolean - with_array.push(StringOrComponent::String( - if *b != 0 { "true" } else { "false" }.to_string(), + let mut with_array = Vec::new(); + match with.list()? { + simdnbt::borrow::NbtList::Empty => {} + simdnbt::borrow::NbtList::String(with) => { + for item in with { + with_array.push(StringOrComponent::String(item.to_string())); + } + } + simdnbt::borrow::NbtList::Compound(with) => { + for item in with { + // if it's a string component with no styling and no siblings, + // just add a string to + // with_array otherwise add the + // component to the array + if let Some(primitive) = item.get("") { + // minecraft does this sometimes, for example + // for the /give system messages + match primitive { + simdnbt::borrow::NbtTag::Byte(b) => { + // interpreted as boolean + with_array.push(StringOrComponent::String( + if *b != 0 { "true" } else { "false" } + .to_string(), + )); + } + simdnbt::borrow::NbtTag::Short(s) => { + with_array + .push(StringOrComponent::String(s.to_string())); + } + simdnbt::borrow::NbtTag::Int(i) => { + with_array + .push(StringOrComponent::String(i.to_string())); + } + simdnbt::borrow::NbtTag::Long(l) => { + with_array + .push(StringOrComponent::String(l.to_string())); + } + simdnbt::borrow::NbtTag::Float(f) => { + with_array + .push(StringOrComponent::String(f.to_string())); + } + simdnbt::borrow::NbtTag::Double(d) => { + with_array + .push(StringOrComponent::String(d.to_string())); + } + simdnbt::borrow::NbtTag::String(s) => { + with_array + .push(StringOrComponent::String(s.to_string())); + } + _ => { + warn!("couldn't parse {item:?} as FormattedText because it has a disallowed primitive"); + with_array.push(StringOrComponent::String( + "?".to_string(), + )); + } + } + } else if let Some(c) = FormattedText::from_nbt_tag( + &simdnbt::borrow::NbtTag::Compound(item.clone()), + ) { + if let FormattedText::Text(text_component) = c { + if text_component.base.siblings.is_empty() + && text_component.base.style.is_empty() + { + with_array.push(StringOrComponent::String( + text_component.text, + )); + continue; + } + } + with_array.push(StringOrComponent::FormattedText( + FormattedText::from_nbt_tag( + &simdnbt::borrow::NbtTag::Compound(item.clone()), + )?, )); - } - simdnbt::borrow::NbtTag::Short(s) => { - with_array.push(StringOrComponent::String(s.to_string())); - } - simdnbt::borrow::NbtTag::Int(i) => { - with_array.push(StringOrComponent::String(i.to_string())); - } - simdnbt::borrow::NbtTag::Long(l) => { - with_array.push(StringOrComponent::String(l.to_string())); - } - simdnbt::borrow::NbtTag::Float(f) => { - with_array.push(StringOrComponent::String(f.to_string())); - } - simdnbt::borrow::NbtTag::Double(d) => { - with_array.push(StringOrComponent::String(d.to_string())); - } - simdnbt::borrow::NbtTag::String(s) => { - with_array.push(StringOrComponent::String(s.to_string())); - } - _ => { - warn!("couldn't parse {item:?} as FormattedText because it has a disallowed primitive"); + } else { + warn!("couldn't parse {item:?} as FormattedText"); with_array.push(StringOrComponent::String("?".to_string())); } } - } else if let Some(c) = FormattedText::from_nbt_tag( - &simdnbt::borrow::NbtTag::Compound(item.clone()), - ) { - if let FormattedText::Text(text_component) = c { - if text_component.base.siblings.is_empty() - && text_component.base.style.is_empty() - { - with_array - .push(StringOrComponent::String(text_component.text)); - continue; - } - } - with_array.push(StringOrComponent::FormattedText( - FormattedText::from_nbt_tag( - &simdnbt::borrow::NbtTag::Compound(item.clone()), - )?, - )); - } else { - warn!("couldn't parse {item:?} as FormattedText"); - with_array.push(StringOrComponent::String("?".to_string())); + } + _ => { + warn!("couldn't parse {with:?} as FormattedText because it's not a list of compounds"); + return None; } } component = FormattedText::Translatable(TranslatableComponent::new( @@ -448,8 +472,9 @@ impl McBufReadable for FormattedText { fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result { let nbt = simdnbt::borrow::NbtTag::read_optional(buf)?; if let Some(nbt) = nbt { - FormattedText::from_nbt_tag(&nbt) - .ok_or(BufReadError::Custom("couldn't read nbt".to_owned())) + FormattedText::from_nbt_tag(&nbt).ok_or(BufReadError::Custom( + "couldn't convert nbt to chat message".to_owned(), + )) } else { Ok(FormattedText::default()) } diff --git a/azalea-protocol/src/packets/game/clientbound_system_chat_packet.rs b/azalea-protocol/src/packets/game/clientbound_system_chat_packet.rs index 420dfd36f..691a62a15 100755 --- a/azalea-protocol/src/packets/game/clientbound_system_chat_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_system_chat_packet.rs @@ -29,4 +29,17 @@ mod tests { "[py5: Gave 1 [Diamond Pickaxe] to py5]".to_string() ); } + + #[test] + fn test_translate_with_string_array_clientbound_system_chat_packet() { + #[rustfmt::skip] + let bytes = [ + 10, 9, 0, 4, 119, 105, 116, 104, 8, 0, 0, 0, 1, 0, 14, 109, 105, 110, 101, 99, 114, 97, 102, 116, 58, 100, 117, 115, 116, 8, 0, 9, 116, 114, 97, 110, 115, 108, 97, 116, 101, 0, 25, 99, 111, 109, 109, 97, 110, 100, 115, 46, 112, 97, 114, 116, 105, 99, 108, 101, 46, 115, 117, 99, 99, 101, 115, 115, 0, 0 + ]; + let packet = ClientboundSystemChatPacket::read_from(&mut Cursor::new(&bytes)).unwrap(); + assert_eq!( + packet.content.to_string(), + "Displaying particle minecraft:dust".to_string() + ); + } }