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::*;