aboutsummaryrefslogtreecommitdiff
path: root/azalea-protocol
diff options
context:
space:
mode:
authorEightFactorial <murphkev000@gmail.com>2022-12-06 18:48:48 -0800
committerGitHub <noreply@github.com>2022-12-06 20:48:48 -0600
commit9f5e5c092be9167e4d5222fdee4a1d2c419e5052 (patch)
tree1d0a8b57434e0afd14b4a02cbbc579a3ad70da61 /azalea-protocol
parente99a822995c80e1f95c5f7a69e0d8c5d131af20f (diff)
downloadazalea-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')
-rwxr-xr-xazalea-protocol/Cargo.toml22
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_command_suggestions_packet.rs48
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_commands_packet.rs259
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs146
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(())
}
}