diff options
| author | EightFactorial <murphkev000@gmail.com> | 2022-12-06 18:48:48 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-06 20:48:48 -0600 |
| commit | 9f5e5c092be9167e4d5222fdee4a1d2c419e5052 (patch) | |
| tree | 1d0a8b57434e0afd14b4a02cbbc579a3ad70da61 /azalea-protocol | |
| parent | e99a822995c80e1f95c5f7a69e0d8c5d131af20f (diff) | |
| download | azalea-drasl-9f5e5c092be9167e4d5222fdee4a1d2c419e5052.tar.xz | |
Complete ClientboundCommand{Suggestion}sPacket, Serde support for NBT Tags (#49)
* Serializing ClientboundStatusResponsePacket
Enable serialization of ClientboundStatusResponsePacket
* Update clientbound_status_response_packet.rs
Add options previewsChat and enforcesSecureChat
* Serialize Style and TextColor
* Serialize BaseComponent
* Serialize TextComponent
* Fix Style
* Serialize Component
* Fix multiple formats per message, fix reset tag
* Fix Style, again
* Use FlatMapSerializer
* Forgot italics
* Count struct fields, reorganize logic
* Serialize TranslatableComponent
* Rewrite TextComponent Serializer
* Fix using TextColor::Parse
* Code Cleanup
* Add default attribute, just in case
* Clippy
* use serde derive feature + preferred formatting choices
* McBufWritable for BrigadierNodeStub
* Thanks Clippy...
* Implement suggestions in azalea-brigadier
* Serde support for NBT Tags
* Serde options
* Forgot Options
* Oops, that's McBufWritable for BrigadierParser
* Fix McBufWritable for SlotData
* Complete ClientboundUpdateRecipesPacket
* fix some issues
* better impl McBufReadable for Suggestions
Co-authored-by: BuildTools <unconfigured@null.spigotmc.org>
Co-authored-by: mat <github@matdoes.dev>
Diffstat (limited to 'azalea-protocol')
4 files changed, 433 insertions, 42 deletions
diff --git a/azalea-protocol/Cargo.toml b/azalea-protocol/Cargo.toml index f9cf7d86..32ec5b90 100755 --- a/azalea-protocol/Cargo.toml +++ b/azalea-protocol/Cargo.toml @@ -11,17 +11,17 @@ version = "0.4.0" [dependencies] async-compression = {version = "^0.3.8", features = ["tokio", "zlib"], optional = true} async-recursion = "1.0.0" -azalea-auth = {path = "../azalea-auth", version = "^0.4.0" } -azalea-block = {path = "../azalea-block", default-features = false, version = "^0.4.0" } -azalea-brigadier = {path = "../azalea-brigadier", version = "^0.4.0" } -azalea-buf = {path = "../azalea-buf", version = "^0.4.0" } -azalea-chat = {path = "../azalea-chat", version = "^0.4.0" } -azalea-core = {path = "../azalea-core", optional = true, version = "^0.4.0" } -azalea-crypto = {path = "../azalea-crypto", version = "^0.4.0" } -azalea-nbt = {path = "../azalea-nbt", version = "^0.4.0" } -azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.4.0" } -azalea-registry = {path = "../azalea-registry", version = "^0.4.0" } -azalea-world = {path = "../azalea-world", version = "^0.4.0" } +azalea-auth = {path = "../azalea-auth", version = "^0.4.0"} +azalea-block = {path = "../azalea-block", default-features = false, version = "^0.4.0"} +azalea-brigadier = {path = "../azalea-brigadier", version = "^0.4.0", features = ["azalea-buf"]} +azalea-buf = {path = "../azalea-buf", version = "^0.4.0"} +azalea-chat = {path = "../azalea-chat", version = "^0.4.0"} +azalea-core = {path = "../azalea-core", optional = true, version = "^0.4.0"} +azalea-crypto = {path = "../azalea-crypto", version = "^0.4.0"} +azalea-nbt = {path = "../azalea-nbt", version = "^0.4.0"} +azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.4.0"} +azalea-registry = {path = "../azalea-registry", version = "^0.4.0"} +azalea-world = {path = "../azalea-world", version = "^0.4.0"} byteorder = "^1.4.3" bytes = "^1.1.0" flate2 = "1.0.23" diff --git a/azalea-protocol/src/packets/game/clientbound_command_suggestions_packet.rs b/azalea-protocol/src/packets/game/clientbound_command_suggestions_packet.rs index c6f426a9..652ce78a 100755 --- a/azalea-protocol/src/packets/game/clientbound_command_suggestions_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_command_suggestions_packet.rs @@ -1,32 +1,36 @@ -// use azalea_brigadier::context::StringRange; -use azalea_buf::{ - // BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable, - BufReadError, - McBufReadable, - McBufWritable, -}; +use azalea_brigadier::suggestion::Suggestions; +use azalea_buf::McBuf; +use azalea_chat::Component; use azalea_protocol_macros::ClientboundGamePacket; -use std::io::{Cursor, Write}; -#[derive(Clone, Debug, ClientboundGamePacket)] +#[derive(Clone, Debug, McBuf, ClientboundGamePacket)] pub struct ClientboundCommandSuggestionsPacket { #[var] pub id: u32, - // pub suggestions: Suggestions, + pub suggestions: Suggestions<Component>, } -impl McBufReadable for ClientboundCommandSuggestionsPacket { - fn read_from(_buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { - // let id = u32::var_read_from(buf)?; - // let start = u32::var_read_from(buf)? as usize; - // let length = u32::var_read_from(buf)? as usize; - // let stringrange = StringRange::between(start, start + length); - todo!("Suggestions aren't implemented in azalea-brigadier yet") - } -} +#[cfg(test)] +mod tests { + use super::*; + use azalea_brigadier::{context::StringRange, suggestion::Suggestion}; + use azalea_buf::{McBufReadable, McBufWritable}; + use std::io::Cursor; -impl McBufWritable for ClientboundCommandSuggestionsPacket { - fn write_into(&self, _buf: &mut impl Write) -> Result<(), std::io::Error> { - todo!() + #[test] + fn test_suggestions() { + let suggestions = Suggestions { + range: StringRange::new(0, 5), + suggestions: vec![Suggestion { + text: "foo".to_string(), + range: StringRange::new(1, 4), + tooltip: Some(Component::from("bar".to_string())), + }], + }; + let mut buf = Vec::new(); + suggestions.write_into(&mut buf).unwrap(); + let mut cursor = Cursor::new(&buf[..]); + let suggestions = Suggestions::read_from(&mut cursor).unwrap(); + assert_eq!(suggestions, suggestions); } } diff --git a/azalea-protocol/src/packets/game/clientbound_commands_packet.rs b/azalea-protocol/src/packets/game/clientbound_commands_packet.rs index 2505d2d9..dcaf8d66 100755 --- a/azalea-protocol/src/packets/game/clientbound_commands_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_commands_packet.rs @@ -1,7 +1,7 @@ use azalea_buf::BufReadError; use azalea_buf::McBuf; use azalea_buf::McBufVarReadable; -use azalea_buf::{McBufReadable, McBufWritable}; +use azalea_buf::{McBufReadable, McBufVarWritable, McBufWritable}; use azalea_core::ResourceLocation; use azalea_protocol_macros::ClientboundGamePacket; use log::warn; @@ -25,8 +25,13 @@ pub struct BrigadierNodeStub { #[derive(Debug, Clone)] pub struct BrigadierNumber<T> { - min: Option<T>, - max: Option<T>, + pub min: Option<T>, + pub max: Option<T>, +} +impl<T> BrigadierNumber<T> { + pub fn new(min: Option<T>, max: Option<T>) -> BrigadierNumber<T> { + BrigadierNumber { min, max } + } } impl<T: McBufReadable> McBufReadable for BrigadierNumber<T> { fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { @@ -119,7 +124,6 @@ pub enum BrigadierParser { Dimension, Uuid, NbtTag, - NbtCompoundTag, Time, ResourceOrTag { registry_key: ResourceLocation }, Resource { registry_key: ResourceLocation }, @@ -157,7 +161,7 @@ impl McBufReadable for BrigadierParser { 16 => Ok(BrigadierParser::Color), 17 => Ok(BrigadierParser::Component), 18 => Ok(BrigadierParser::Message), - 19 => Ok(BrigadierParser::NbtCompoundTag), + 19 => Ok(BrigadierParser::Nbt), 20 => Ok(BrigadierParser::NbtTag), 21 => Ok(BrigadierParser::NbtPath), 22 => Ok(BrigadierParser::Objective), @@ -202,6 +206,181 @@ impl McBufReadable for BrigadierParser { } } +impl McBufWritable for BrigadierParser { + fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { + match &self { + BrigadierParser::Bool => { + u32::var_write_into(&0, buf)?; + } + BrigadierParser::Float(f) => { + u32::var_write_into(&1, buf)?; + f.write_into(buf)?; + } + BrigadierParser::Double(d) => { + u32::var_write_into(&2, buf)?; + d.write_into(buf)?; + } + BrigadierParser::Integer(i) => { + u32::var_write_into(&3, buf)?; + i.write_into(buf)?; + } + BrigadierParser::Long(l) => { + u32::var_write_into(&4, buf)?; + l.write_into(buf)?; + } + BrigadierParser::String(s) => { + u32::var_write_into(&5, buf)?; + s.write_into(buf)?; + } + BrigadierParser::Entity { + single, + players_only, + } => { + u32::var_write_into(&6, buf)?; + let mut bitmask: u8 = 0x00; + if *single { + bitmask |= 0x01; + } + if *players_only { + bitmask |= 0x02; + } + bitmask.write_into(buf)?; + } + BrigadierParser::GameProfile => { + u32::var_write_into(&7, buf)?; + } + BrigadierParser::BlockPos => { + u32::var_write_into(&8, buf)?; + } + BrigadierParser::ColumnPos => { + u32::var_write_into(&9, buf)?; + } + BrigadierParser::Vec3 => { + u32::var_write_into(&10, buf)?; + } + BrigadierParser::Vec2 => { + u32::var_write_into(&11, buf)?; + } + BrigadierParser::BlockState => { + u32::var_write_into(&12, buf)?; + } + BrigadierParser::BlockPredicate => { + u32::var_write_into(&13, buf)?; + } + BrigadierParser::ItemStack => { + u32::var_write_into(&14, buf)?; + } + BrigadierParser::ItemPredicate => { + u32::var_write_into(&15, buf)?; + } + BrigadierParser::Color => { + u32::var_write_into(&16, buf)?; + } + BrigadierParser::Component => { + u32::var_write_into(&17, buf)?; + } + BrigadierParser::Message => { + u32::var_write_into(&18, buf)?; + } + BrigadierParser::Nbt => { + u32::var_write_into(&19, buf)?; + } + BrigadierParser::NbtTag => { + u32::var_write_into(&20, buf)?; + } + BrigadierParser::NbtPath => { + u32::var_write_into(&21, buf)?; + } + BrigadierParser::Objective => { + u32::var_write_into(&22, buf)?; + } + BrigadierParser::ObjectiveCriteira => { + u32::var_write_into(&23, buf)?; + } + BrigadierParser::Operation => { + u32::var_write_into(&24, buf)?; + } + BrigadierParser::Particle => { + u32::var_write_into(&25, buf)?; + } + BrigadierParser::Angle => { + u32::var_write_into(&26, buf)?; + } + BrigadierParser::Rotation => { + u32::var_write_into(&27, buf)?; + } + BrigadierParser::ScoreboardSlot => { + u32::var_write_into(&28, buf)?; + } + BrigadierParser::ScoreHolder { allows_multiple } => { + u32::var_write_into(&29, buf)?; + if *allows_multiple { + buf.write_all(&[0x01])?; + } else { + buf.write_all(&[0x00])?; + } + } + BrigadierParser::Swizzle => { + u32::var_write_into(&30, buf)?; + } + BrigadierParser::Team => { + u32::var_write_into(&31, buf)?; + } + BrigadierParser::ItemSlot => { + u32::var_write_into(&32, buf)?; + } + BrigadierParser::ResourceLocation => { + u32::var_write_into(&33, buf)?; + } + BrigadierParser::MobEffect => { + u32::var_write_into(&34, buf)?; + } + BrigadierParser::Function => { + u32::var_write_into(&35, buf)?; + } + BrigadierParser::EntityAnchor => { + u32::var_write_into(&36, buf)?; + } + BrigadierParser::IntRange => { + u32::var_write_into(&37, buf)?; + } + BrigadierParser::FloatRange => { + u32::var_write_into(&38, buf)?; + } + BrigadierParser::ItemEnchantment => { + u32::var_write_into(&39, buf)?; + } + BrigadierParser::EntitySummon => { + u32::var_write_into(&40, buf)?; + } + BrigadierParser::Dimension => { + u32::var_write_into(&41, buf)?; + } + BrigadierParser::Time => { + u32::var_write_into(&42, buf)?; + } + BrigadierParser::ResourceOrTag { registry_key } => { + u32::var_write_into(&43, buf)?; + registry_key.write_into(buf)?; + } + BrigadierParser::Resource { registry_key } => { + u32::var_write_into(&44, buf)?; + registry_key.write_into(buf)?; + } + BrigadierParser::TemplateMirror => { + u32::var_write_into(&45, buf)?; + } + BrigadierParser::TemplateRotation => { + u32::var_write_into(&46, buf)?; + } + BrigadierParser::Uuid => { + u32::var_write_into(&47, buf)?; + } + } + Ok(()) + } +} + // TODO: BrigadierNodeStub should have more stuff impl McBufReadable for BrigadierNodeStub { fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { @@ -264,8 +443,74 @@ impl McBufReadable for BrigadierNodeStub { } impl McBufWritable for BrigadierNodeStub { - fn write_into(&self, _buf: &mut impl Write) -> Result<(), std::io::Error> { - todo!() + fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { + match &self.node_type { + NodeType::Root => { + let mut flags = 0x00; + if self.is_executable { + flags |= 0x04; + } + if self.redirect_node.is_some() { + flags |= 0x08; + } + flags.var_write_into(buf)?; + + self.children.var_write_into(buf)?; + + if let Some(redirect) = self.redirect_node { + redirect.var_write_into(buf)?; + } + } + NodeType::Literal { name } => { + let mut flags = 0x01; + if self.is_executable { + flags |= 0x04; + } + if self.redirect_node.is_some() { + flags |= 0x08; + } + flags.var_write_into(buf)?; + + self.children.var_write_into(buf)?; + + if let Some(redirect) = self.redirect_node { + redirect.var_write_into(buf)?; + } + + name.write_into(buf)?; + } + NodeType::Argument { + name, + parser, + suggestions_type, + } => { + let mut flags = 0x02; + if self.is_executable { + flags |= 0x04; + } + if self.redirect_node.is_some() { + flags |= 0x08; + } + if suggestions_type.is_some() { + flags |= 0x10; + } + flags.var_write_into(buf)?; + + self.children.var_write_into(buf)?; + + if let Some(redirect) = self.redirect_node { + redirect.var_write_into(buf)?; + } + + name.write_into(buf)?; + parser.write_into(buf)?; + + if let Some(suggestion) = suggestions_type { + suggestion.write_into(buf)?; + } + } + } + Ok(()) } } diff --git a/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs index db31ef78..9c325d29 100755 --- a/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs @@ -121,8 +121,150 @@ pub struct Ingredient { } impl McBufWritable for Recipe { - fn write_into(&self, _buf: &mut impl Write) -> Result<(), std::io::Error> { - todo!() + fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { + match &self.data { + RecipeData::CraftingShapeless(recipe) => { + ResourceLocation::new("minecraft:crafting_shapeless") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + recipe.write_into(buf)?; + } + RecipeData::CraftingShaped(recipe) => { + ResourceLocation::new("minecraft:crafting_shaped") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + recipe.write_into(buf)?; + } + RecipeData::CraftingSpecialArmorDye => { + ResourceLocation::new("minecraft:crafting_special_armordye") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialBookCloning => { + ResourceLocation::new("minecraft:crafting_special_bookcloning") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialMapCloning => { + ResourceLocation::new("minecraft:crafting_special_mapcloning") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialMapExtending => { + ResourceLocation::new("minecraft:crafting_special_mapextending") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialFireworkRocket => { + ResourceLocation::new("minecraft:crafting_special_firework_rocket") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialFireworkStar => { + ResourceLocation::new("minecraft:crafting_special_firework_star") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialFireworkStarFade => { + ResourceLocation::new("minecraft:crafting_special_firework_star_fade") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialRepairItem => { + ResourceLocation::new("minecraft:crafting_special_repairitem") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialTippedArrow => { + ResourceLocation::new("minecraft:crafting_special_tippedarrow") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialBannerDuplicate => { + ResourceLocation::new("minecraft:crafting_special_bannerduplicate") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialBannerAddPattern => { + ResourceLocation::new("minecraft:crafting_special_banneraddpattern") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialShieldDecoration => { + ResourceLocation::new("minecraft:crafting_special_shielddecoration") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialShulkerBoxColoring => { + ResourceLocation::new("minecraft:crafting_special_shulkerboxcoloring") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::CraftingSpecialSuspiciousStew => { + ResourceLocation::new("minecraft:crafting_special_suspiciousstew") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + } + RecipeData::Smelting(recipe) => { + ResourceLocation::new("minecraft:smelting") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + recipe.write_into(buf)?; + } + RecipeData::Blasting(recipe) => { + ResourceLocation::new("minecraft:blasting") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + recipe.write_into(buf)?; + } + RecipeData::Smoking(recipe) => { + ResourceLocation::new("minecraft:smoking") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + recipe.write_into(buf)?; + } + RecipeData::CampfireCooking(recipe) => { + ResourceLocation::new("minecraft:campfire_cooking") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + recipe.write_into(buf)?; + } + RecipeData::Stonecutting(recipe) => { + ResourceLocation::new("minecraft:stonecutting") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + recipe.write_into(buf)?; + } + RecipeData::Smithing(recipe) => { + ResourceLocation::new("minecraft:smithing") + .unwrap() + .write_into(buf)?; + self.identifier.write_into(buf)?; + recipe.write_into(buf)?; + } + }; + Ok(()) } } |
