From ec316e02cd7d86829614ec1c0b7e3edadad103c5 Mon Sep 17 00:00:00 2001 From: mat Date: Wed, 7 Sep 2022 21:30:05 -0500 Subject: [PATCH] fix ClientboundUpdateAdvancementsPacket --- azalea-buf/azalea-buf-macros/src/lib.rs | 1 - azalea-chat/src/component.rs | 81 +++-------- .../clientbound_update_advancements_packet.rs | 137 ++++++++++++++---- 3 files changed, 128 insertions(+), 91 deletions(-) diff --git a/azalea-buf/azalea-buf-macros/src/lib.rs b/azalea-buf/azalea-buf-macros/src/lib.rs index 07b2e5ef..c8d62569 100644 --- a/azalea-buf/azalea-buf-macros/src/lib.rs +++ b/azalea-buf/azalea-buf-macros/src/lib.rs @@ -167,7 +167,6 @@ fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt let mut variant_discrim: u32 = 0; let mut first = true; for variant in variants { - let variant_name = &variant.ident; match &variant.discriminant.as_ref() { Some(d) => { variant_discrim = match &d.1 { diff --git a/azalea-chat/src/component.rs b/azalea-chat/src/component.rs index 59b1779e..caf50b0a 100755 --- a/azalea-chat/src/component.rs +++ b/azalea-chat/src/component.rs @@ -126,18 +126,18 @@ impl<'de> Deserialize<'de> for Component { } // if it's an object, do things with { text } and stuff else if json.is_object() { - if json.get("text").is_some() { - let text = json.get("text").unwrap().as_str().unwrap_or("").to_string(); + if let Some(text) = json.get("text") { + let text = text.as_str().unwrap_or("").to_string(); component = Component::Text(TextComponent::new(text)); - } else if json.get("translate").is_some() { - let translate = json - .get("translate") - .unwrap() + } else if let Some(translate) = json.get("translate") { + let translate = translate .as_str() .ok_or_else(|| de::Error::custom("\"translate\" must be a string"))? .into(); - if json.get("with").is_some() { - let with = json.get("with").unwrap().as_array().unwrap(); + if let Some(with) = json.get("with") { + let with = with + .as_array() + .ok_or_else(|| de::Error::custom("\"with\" must be an array"))?; 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 @@ -162,12 +162,9 @@ impl<'de> Deserialize<'de> for Component { component = Component::Translatable(TranslatableComponent::new(translate, Vec::new())); } - } else if json.get("score").is_some() { + } else if let Some(score) = json.get("score") { // object = GsonHelper.getAsJsonObject(jsonObject, "score"); - let score_json = json.get("score").unwrap(); - // if (!object.has("name") || !object.has("objective")) throw new JsonParseException("A score component needs a least a name and an objective"); - // ScoreComponent scoreComponent = new ScoreComponent(GsonHelper.getAsString((JsonObject)object, "name"), GsonHelper.getAsString((JsonObject)object, "objective")); - if score_json.get("name").is_none() || score_json.get("objective").is_none() { + if score.get("name").is_none() || score.get("objective").is_none() { return Err(de::Error::missing_field( "A score component needs at least a name and an objective", )); @@ -176,65 +173,35 @@ impl<'de> Deserialize<'de> for Component { return Err(de::Error::custom( "score text components aren't yet supported", )); - // component = ScoreComponent } else if json.get("selector").is_some() { - // } else if (jsonObject.has("selector")) { - // object = this.parseSeparator(type, jsonDeserializationContext, jsonObject); - // SelectorComponent selectorComponent = new SelectorComponent(GsonHelper.getAsString(jsonObject, "selector"), (Optional)object); - return Err(de::Error::custom( "selector text components aren't yet supported", )); - // } else if (jsonObject.has("keybind")) { - // KeybindComponent keybindComponent = new KeybindComponent(GsonHelper.getAsString(jsonObject, "keybind")); } else if json.get("keybind").is_some() { return Err(de::Error::custom( "keybind text components aren't yet supported", )); } else { - // } else { - // if (!jsonObject.has("nbt")) throw new JsonParseException("Don't know how to turn " + jsonElement + " into a Component"); - if json.get("nbt").is_none() { + let nbt = if let Some(nbt) = json.get("nbt") { + nbt + } else { return Err(de::Error::custom( format!("Don't know how to turn {} into a Component", json).as_str(), )); - } - // object = GsonHelper.getAsString(jsonObject, "nbt"); - let _nbt = json.get("nbt").unwrap().to_string(); - // Optional optional = this.parseSeparator(type, jsonDeserializationContext, jsonObject); + }; let _separator = Component::parse_separator(&json).map_err(de::Error::custom)?; let _interpret = match json.get("interpret") { Some(v) => v.as_bool().ok_or(Some(false)).unwrap(), None => false, }; - // boolean bl = GsonHelper.getAsBoolean(jsonObject, "interpret", false); - // if (jsonObject.has("block")) { - if json.get("block").is_some() {} + if let Some(_block) = json.get("block") {} return Err(de::Error::custom( "nbt text components aren't yet supported", )); - // NbtComponent.BlockNbtComponent blockNbtComponent = new NbtComponent.BlockNbtComponent((String)object, bl, GsonHelper.getAsString(jsonObject, "block"), optional); - // } else if (jsonObject.has("entity")) { - // NbtComponent.EntityNbtComponent entityNbtComponent = new NbtComponent.EntityNbtComponent((String)object, bl, GsonHelper.getAsString(jsonObject, "entity"), optional); - // } else { - // if (!jsonObject.has("storage")) throw new JsonParseException("Don't know how to turn " + jsonElement + " into a Component"); - // NbtComponent.StorageNbtComponent storageNbtComponent = new NbtComponent.StorageNbtComponent((String)object, bl, new ResourceLocation(GsonHelper.getAsString(jsonObject, "storage")), optional); - // } - // } } - // if (jsonObject.has("extra")) { - // object = GsonHelper.getAsJsonArray(jsonObject, "extra"); - // if (object.size() <= 0) throw new JsonParseException("Unexpected empty array of components"); - // for (int i = 0; i < object.size(); ++i) { - // var5_17.append(this.deserialize(object.get(i), type, jsonDeserializationContext)); - // } - // } - // var5_17.setStyle((Style)jsonDeserializationContext.deserialize(jsonElement, Style.class)); - // return var5_17; - // } - if json.get("extra").is_some() { - let extra = match json.get("extra").unwrap().as_array() { + if let Some(extra) = json.get("extra") { + let extra = match extra.as_array() { Some(r) => r, None => return Err(de::Error::custom("Extra isn't an array")), }; @@ -281,18 +248,10 @@ impl McBufReadable for Component { } impl McBufWritable for Component { - // async fn read_from(buf: &mut impl Read) -> Result - // where - // R: AsyncRead + std::marker::Unpin + std::marker::Send, - // { - // let string = String::read_from(buf).await?; - // let json: serde_json::Value = serde_json::from_str(string.as_str()) - // .map_err(|e| "Component isn't valid JSON".to_string())?; - // let component = Component::deserialize(json).map_err(|e| e.to_string())?; - // Ok(component) - // } fn write_into(&self, _buf: &mut impl Write) -> Result<(), std::io::Error> { - // component doesn't have serialize implemented yet + // let json = serde_json::to_string(self).unwrap(); + // json.write_into(_buf); + // Ok(()) todo!() } } diff --git a/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs index f0f33b36..f7adcafa 100644 --- a/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs @@ -1,11 +1,8 @@ -use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable}; +use azalea_buf::McBuf; use azalea_chat::component::Component; use azalea_core::{ResourceLocation, Slot}; use azalea_protocol_macros::ClientboundGamePacket; -use std::{ - collections::HashMap, - io::{Read, Write}, -}; +use std::collections::HashMap; #[derive(Clone, Debug, McBuf, ClientboundGamePacket)] pub struct ClientboundUpdateAdvancementsPacket { @@ -25,40 +22,28 @@ pub struct Advancement { // requirements_strategy: RequirementsStrategy.AND } -#[derive(Clone, Debug, McBuf)] +#[derive(Clone, Debug)] pub struct DisplayInfo { pub title: Component, pub description: Component, pub icon: Slot, pub frame: FrameType, - pub flags: DisplayFlags, + pub show_toast: bool, + pub hidden: bool, pub background: Option, pub x: f32, pub y: f32, } -#[derive(Clone, Debug)] -pub struct DisplayFlags { - pub background: bool, - pub show_toast: bool, - pub hidden: bool, -} +impl azalea_buf::McBufWritable for DisplayInfo { + fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> { + self.title.write_into(buf)?; + self.description.write_into(buf)?; + self.icon.write_into(buf)?; + self.frame.write_into(buf)?; -impl McBufReadable for DisplayFlags { - fn read_from(buf: &mut impl Read) -> Result { - let data = u32::read_from(buf)?; - Ok(DisplayFlags { - background: (data & 0b1) != 0, - show_toast: (data & 0b10) != 0, - hidden: (data & 0b100) != 0, - }) - } -} - -impl McBufWritable for DisplayFlags { - fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - let mut data = 0; - if self.background { + let mut data: u32 = 0; + if self.background.is_some() { data |= 0b1; } if self.show_toast { @@ -67,7 +52,46 @@ impl McBufWritable for DisplayFlags { if self.hidden { data |= 0b100; } - u32::write_into(&data, buf) + data.write_into(buf)?; + + if let Some(background) = &self.background { + background.write_into(buf)?; + } + self.x.write_into(buf)?; + self.y.write_into(buf)?; + Ok(()) + } +} +impl azalea_buf::McBufReadable for DisplayInfo { + fn read_from(buf: &mut impl std::io::Read) -> Result { + let title = azalea_buf::McBufReadable::read_from(buf)?; + let description = azalea_buf::McBufReadable::read_from(buf)?; + let icon = azalea_buf::McBufReadable::read_from(buf)?; + let frame = azalea_buf::McBufReadable::read_from(buf)?; + + let data = u32::read_from(buf)?; + let has_background = (data & 0b1) != 0; + let show_toast = (data & 0b10) != 0; + let hidden = (data & 0b100) != 0; + + let background = if has_background { + Some(ResourceLocation::read_from(buf)?) + } else { + None + }; + let x = azalea_buf::McBufReadable::read_from(buf)?; + let y = azalea_buf::McBufReadable::read_from(buf)?; + Ok(DisplayInfo { + title, + description, + icon, + frame, + background, + x, + y, + hidden, + show_toast, + }) } } @@ -88,3 +112,58 @@ pub type AdvancementProgress = HashMap; pub struct CriterionProgress { date: Option, } + +// #[cfg(test)] +// mod tests { +// use super::*; +// use azalea_buf::{McBufReadable, McBufWritable}; +// use azalea_core::ResourceLocation; +// use azalea_protocol_macros::ClientboundGamePacket; +// use std::io::Cursor; + +// #[test] +// fn test() { +// let mut buf = Cursor::new(Vec::new()); +// let packet = ClientboundUpdateAdvancementsPacket { +// reset: true, +// added: [( +// ResourceLocation::new("minecraft:test").unwrap(), +// Advancement { +// parent_id: None, +// display: Some(DisplayInfo { +// title: Component::from("title".to_string()), +// description: Component::from("description".to_string()), +// icon: Slot::Empty, +// frame: FrameType::Task, +// show_toast: true, +// hidden: false, +// background: None, +// x: 0.0, +// y: 0.0, +// }), +// criteria: HashMap::new(), +// requirements: Vec::new(), +// }, +// )] +// .into_iter() +// .collect(), +// removed: vec![ResourceLocation::new("minecraft:test2").unwrap()], +// progress: [( +// ResourceLocation::new("minecraft:test3").unwrap(), +// [( +// ResourceLocation::new("minecraft:test4").unwrap(), +// CriterionProgress { +// date: Some(123456789), +// }, +// )] +// .into_iter() +// .collect(), +// )] +// .into_iter() +// .collect(), +// }; +// packet.write_into(&mut buf).unwrap(); +// let packet = ClientboundUpdateAdvancementsPacket::read_from(&mut buf).unwrap(); +// assert_eq!(packet.reset, true); +// } +// }