From ad8bcf6abafcb8e237ab2bc34447923b3d24acc8 Mon Sep 17 00:00:00 2001 From: iceiix <43691553+iceiix@users.noreply.github.com> Date: Sun, 2 Dec 2018 19:32:52 -0800 Subject: [PATCH] 1.12.2 protocol support (340) (#40) * Add new 1.12.2 packets and shift IDs CraftRecipeResponse AdvancementTab SelectAdvancementTab Advancements CraftingRecipeRequest UnlockRecipes CraftingBookData * Fix unlock recipes packet, add length-prefixed arrays https://wiki.vg/index.php?title=Protocol&oldid=14204#Unlock_Recipes * Update resources to 1.12.2 * Handle NBTTag metadata (value 13), parsed as nbt::NamedTag https://wiki.vg/index.php?title=Entity_metadata&oldid=14048#Entity_Metadata_Format https://github.com/iceiix/steven/pull/40#issuecomment-443454757 * Fix entity packet IDs, 0x25 now is Entity https://wiki.vg/index.php?title=Protocol&oldid=14204#Entity * Add NBT long array (type 12) support https://wiki.vg/NBT#Specification * Entity metadata type is now a VarInt, not u8: https://wiki.vg/index.php?title=Entity_metadata&oldid=14048#Entity_Metadata_Format * Keep alives changed to longs, no longer VarInts https://wiki.vg/index.php?title=Protocol&oldid=14204#Keep_Alive_.28serverbound.29 * Parse CraftRecipeResponse (0x2b) * Add structs for advancements data * Implement Serializable trait for Advancement and AdvancementDisplay * Implement advancement progress parsing; advancement packet works * Particle packet adds fallingdust (46) with length 1 https://wiki.vg/index.php?title=Protocol&oldid=14204#Particle_2 --- protocol/src/nbt/mod.rs | 24 ++++++++++++++++++++++++ protocol/src/types/metadata.rs | 30 +++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index 3e79578..e72fad6 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -34,6 +34,7 @@ pub enum Tag { List(Vec), Compound(HashMap), IntArray(Vec), + LongArray(Vec), } #[derive(Debug, Clone)] @@ -155,6 +156,14 @@ impl Tag { } } + pub fn as_long_array(&self) -> Option<&[i64]> { + match *self { + Tag::LongArray(ref val) => Some(&val[..]), + _ => None, + } + } + + fn internal_id(&self) -> u8 { match *self { Tag::End => 0, @@ -169,6 +178,7 @@ impl Tag { Tag::List(_) => 9, Tag::Compound(_) => 10, Tag::IntArray(_) => 11, + Tag::LongArray(_) => 12, } } @@ -217,6 +227,14 @@ impl Tag { } data })), + 12 => Ok(Tag::LongArray({ + let len: i32 = Serializable::read_from(buf)?; + let mut data = Vec::with_capacity(len as usize); + for _ in 0..len { + data.push(buf.read_i64::()?); + } + data + })), _ => Err(protocol::Error::Err("invalid tag".to_owned())), } } @@ -267,6 +285,12 @@ impl Serializable for Tag { v.write_to(buf)?; } } + Tag::LongArray(ref val) => { + (val.len() as i32).write_to(buf)?; + for v in val { + v.write_to(buf)?; + } + } } Result::Ok(()) } diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 228a034..396b983 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -21,6 +21,7 @@ use crate::protocol::Serializable; use crate::format; use crate::item; use crate::shared::Position; +use crate::nbt; pub struct MetadataKey { index: i32, @@ -68,7 +69,7 @@ impl Serializable for Metadata { if index == 0xFF { break; } - let ty = u8::read_from(buf)?; + let ty = protocol::VarInt::read_from(buf)?.0; match ty { 0 => m.put_raw(index, i8::read_from(buf)?), 1 => m.put_raw(index, protocol::VarInt::read_from(buf)?.0), @@ -98,6 +99,15 @@ impl Serializable for Metadata { } } 12 => m.put_raw(index, protocol::VarInt::read_from(buf)?.0 as u16), + 13 => { + let ty = u8::read_from(buf)?; + if ty != 0 { + let name = nbt::read_string(buf)?; + let tag = nbt::Tag::read_from(buf)?; + + m.put_raw(index, nbt::NamedTag(name, tag)); + } + } _ => return Err(protocol::Error::Err("unknown metadata type".to_owned())), } } @@ -164,6 +174,11 @@ impl Serializable for Metadata { u8::write_to(&11, buf)?; protocol::VarInt(*val as i32).write_to(buf)?; } + Value::NBTTag(ref _val) => { + u8::write_to(&13, buf)?; + // TODO: write NBT tags metadata + //nbt::Tag(*val).write_to(buf)?; + } } } u8::write_to(&0xFF, buf)?; @@ -202,6 +217,7 @@ pub enum Value { Direction(protocol::VarInt), // TODO: Proper type OptionalUUID(Option), Block(u16), // TODO: Proper type + NBTTag(nbt::NamedTag), } pub trait MetaValue { @@ -365,6 +381,18 @@ impl MetaValue for u16 { } } +impl MetaValue for nbt::NamedTag { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::NBTTag(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::NBTTag(self) + } +} + #[cfg(test)] mod test { use super::*;