aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2024-04-20 21:05:51 +0000
committermat <git@matdoes.dev>2024-04-20 21:06:37 +0000
commit0ddad8bd9c7c0e8846aec8bc90c95416418c9a63 (patch)
tree4f19bea48546d830b8a5a13ffb797ebd7c1ced49
parentf919fb65d67891d2eb6e302ea400743963c4c550 (diff)
downloadazalea-drasl-0ddad8bd9c7c0e8846aec8bc90c95416418c9a63.tar.xz
fix edge case with reading FormattedText as nbt
-rwxr-xr-xazalea-chat/src/component.rs139
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_system_chat_packet.rs13
2 files changed, 95 insertions, 57 deletions
diff --git a/azalea-chat/src/component.rs b/azalea-chat/src/component.rs
index d301aba1..55fbd30d 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<Self, BufReadError> {
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 420dfd36..691a62a1 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()
+ );
+ }
}