From fe6a56ce3a5722f5d13d40310802a2632b2e5902 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Thu, 10 Sep 2015 11:49:41 +0100 Subject: [PATCH 01/47] Main part of the protocol complete --- protocol/src/format.rs | 254 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 protocol/src/format.rs diff --git a/protocol/src/format.rs b/protocol/src/format.rs new file mode 100644 index 0000000..a762cc0 --- /dev/null +++ b/protocol/src/format.rs @@ -0,0 +1,254 @@ +extern crate serde_json; + +use std::fmt; + +#[derive(Debug)] +pub enum Component { + Text(TextComponent), + None +} + +impl Component { + pub fn from_value(v: &serde_json::Value) -> Self { + let modifier = Modifier::from_value(v); + if let Some(val) = v.as_string() { + Component::Text(TextComponent{text: val.to_owned(), modifier: modifier}) + } else if v.find("text").is_some(){ + Component::Text(TextComponent::from_value(v, modifier)) + } else { + Component::None + } + } + + pub fn to_value(&self) -> serde_json::Value { + unimplemented!() + } +} + +impl fmt::Display for Component { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Component::Text(ref txt) => write!(f, "{}", txt), + Component::None => Result::Ok(()), + } + } +} + +impl Default for Component { + fn default() -> Self { + Component::None + } +} + +#[derive(Debug)] +pub struct Modifier { + pub extra: Option>, + pub bold: Option, + pub italic: Option, + pub underlined: Option, + pub strikethrough: Option, + pub obfuscated: Option, + pub color: Option, + + // click_event + // hover_event + // insertion +} + +impl Modifier { + pub fn from_value(v: &serde_json::Value) -> Self { + let mut m = Modifier { + bold: v.find("bold").map_or(Option::None, |v| v.as_boolean()), + italic: v.find("italic").map_or(Option::None, |v| v.as_boolean()), + underlined: v.find("underlined").map_or(Option::None, |v| v.as_boolean()), + strikethrough: v.find("strikethrough").map_or(Option::None, |v| v.as_boolean()), + obfuscated: v.find("obfuscated").map_or(Option::None, |v| v.as_boolean()), + color: v.find("color").map_or(Option::None, |v| v.as_string()).map(|v| Color::from_string(&v.to_owned())), + extra: Option::None, + }; + if let Some(extra) = v.find("extra") { + if let Some(data) = extra.as_array() { + let mut ex = Vec::new(); + for e in data { + ex.push(Component::from_value(e)); + } + m.extra = Some(ex); + } + } + m + } + + pub fn to_value(&self) -> serde_json::Value { + unimplemented!() + } +} + +#[derive(Debug)] +pub struct TextComponent { + pub text: String, + pub modifier: Modifier, +} + +impl TextComponent { + pub fn from_value(v: &serde_json::Value, modifier: Modifier) -> Self { + TextComponent { + text: v.find("text").unwrap().as_string().unwrap_or("").to_owned(), + modifier: modifier, + } + } + + pub fn to_value(&self) -> serde_json::Value { + unimplemented!() + } +} + +impl fmt::Display for TextComponent { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{}", self.text)); + if let Some(ref extra) = self.modifier.extra { + for c in extra { + try!(write!(f, "{}", c)); + } + } + Result::Ok(()) + } +} + +#[derive(Debug)] +pub enum Color { + Black, + DarkBlue, + DarkGreen, + DarkAqua, + DarkRed, + DarkPurple, + Gold, + Gray, + DarkGray, + Blue, + Green, + Aqua, + Red, + LightPurple, + Yellow, + White, + RGB(u8, u8, u8) +} + +impl fmt::Display for Color { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_string()) + } +} + +impl Color { + fn from_string(val: &String) -> Self { + match val.as_ref() { + "black" => Color::Black, + "dark_blue" => Color::DarkBlue, + "dark_green" => Color::DarkGreen, + "dark_aqua" => Color::DarkAqua, + "dark_red" => Color::DarkRed, + "dark_purple" => Color::DarkPurple, + "gold" => Color::Gold, + "gray" => Color::Gray, + "dark_gray" => Color::DarkGray, + "blue" => Color::Blue, + "green" => Color::Green, + "aqua" => Color::Aqua, + "red" => Color::Red, + "light_purple" => Color::LightPurple, + "yellow" => Color::Yellow, + "white" => Color::White, + val if val.len() == 7 && val.as_bytes()[0] == b'#' => { + let r = match u8::from_str_radix(&val[1..3], 16) { + Ok(r) => r, + Err(_) => return Color::White, + }; + let g = match u8::from_str_radix(&val[3..5], 16) { + Ok(g) => g, + Err(_) => return Color::White, + }; + let b = match u8::from_str_radix(&val[5..7], 16) { + Ok(b) => b, + Err(_) => return Color::White, + }; + Color::RGB( + r, + g, + b + ) + } + _ => Color::White, + } + } + + fn to_string(&self) -> String { + match *self { + Color::Black => "black".to_owned(), + Color::DarkBlue => "dark_blue".to_owned(), + Color::DarkGreen => "dark_green".to_owned(), + Color::DarkAqua => "dark_aqua".to_owned(), + Color::DarkRed => "dark_red".to_owned(), + Color::DarkPurple => "dark_purple".to_owned(), + Color::Gold => "gold".to_owned(), + Color::Gray => "gray".to_owned(), + Color::DarkGray => "dark_gray".to_owned(), + Color::Blue => "blue".to_owned(), + Color::Green => "green".to_owned(), + Color::Aqua => "aqua".to_owned(), + Color::Red => "red".to_owned(), + Color::LightPurple => "light_purple".to_owned(), + Color::Yellow => "yellow".to_owned(), + Color::White => "white".to_owned(), + Color::RGB(r, g, b) => format!("#{:02X}{:02X}{:02X}", r, g, b), + } + } + + #[allow(dead_code)] + fn to_rgb(&self) -> (u8, u8, u8) { + match *self { + Color::Black =>(0, 0, 0), + Color::DarkBlue =>(0, 0, 170), + Color::DarkGreen =>(0, 170, 0), + Color::DarkAqua =>(0, 170, 170), + Color::DarkRed =>(170, 0, 0), + Color::DarkPurple =>(170, 0, 170), + Color::Gold =>(255, 170, 0), + Color::Gray =>(170, 170, 170), + Color::DarkGray =>(85, 85, 85), + Color::Blue =>(85, 85, 255), + Color::Green =>(85, 255, 85), + Color::Aqua =>(85, 255, 255), + Color::Red =>(255, 85, 85), + Color::LightPurple =>(255, 85, 255), + Color::Yellow =>(255, 255, 85), + Color::White =>(255, 255, 255), + Color::RGB(r, g, b) => (r, g, b), + } + } +} + +#[test] +fn test_color_from() { + let test = Color::from_string(&"#FF0000".to_owned()); + match test { + Color::RGB(r, g, b) => assert!(r == 255 && g == 0 && b == 0), + _ => panic!("Wrong type"), + } + let test = Color::from_string(&"#123456".to_owned()); + match test { + Color::RGB(r, g, b) => assert!(r == 0x12 && g == 0x34 && b == 0x56), + _ => panic!("Wrong type"), + } + let test = Color::from_string(&"red".to_owned()); + match test { + Color::Red => {}, + _ => panic!("Wrong type"), + } + let test = Color::from_string(&"dark_blue".to_owned()); + match test { + Color::DarkBlue => {}, + _ => panic!("Wrong type"), + } +} From 25a033268ceb094f2862ef32e1dddff3faaef3fb Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Thu, 10 Sep 2015 11:58:42 +0100 Subject: [PATCH 02/47] Tabs to spaces --- protocol/src/format.rs | 402 ++++++++++++++++++++--------------------- 1 file changed, 201 insertions(+), 201 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index a762cc0..7928967 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -4,251 +4,251 @@ use std::fmt; #[derive(Debug)] pub enum Component { - Text(TextComponent), - None + Text(TextComponent), + None } impl Component { - pub fn from_value(v: &serde_json::Value) -> Self { - let modifier = Modifier::from_value(v); - if let Some(val) = v.as_string() { - Component::Text(TextComponent{text: val.to_owned(), modifier: modifier}) - } else if v.find("text").is_some(){ - Component::Text(TextComponent::from_value(v, modifier)) - } else { - Component::None - } - } + pub fn from_value(v: &serde_json::Value) -> Self { + let modifier = Modifier::from_value(v); + if let Some(val) = v.as_string() { + Component::Text(TextComponent{text: val.to_owned(), modifier: modifier}) + } else if v.find("text").is_some(){ + Component::Text(TextComponent::from_value(v, modifier)) + } else { + Component::None + } + } - pub fn to_value(&self) -> serde_json::Value { - unimplemented!() - } + pub fn to_value(&self) -> serde_json::Value { + unimplemented!() + } } impl fmt::Display for Component { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Component::Text(ref txt) => write!(f, "{}", txt), - Component::None => Result::Ok(()), - } - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Component::Text(ref txt) => write!(f, "{}", txt), + Component::None => Result::Ok(()), + } + } } impl Default for Component { - fn default() -> Self { - Component::None - } + fn default() -> Self { + Component::None + } } #[derive(Debug)] pub struct Modifier { - pub extra: Option>, - pub bold: Option, - pub italic: Option, - pub underlined: Option, - pub strikethrough: Option, - pub obfuscated: Option, - pub color: Option, + pub extra: Option>, + pub bold: Option, + pub italic: Option, + pub underlined: Option, + pub strikethrough: Option, + pub obfuscated: Option, + pub color: Option, - // click_event - // hover_event - // insertion + // click_event + // hover_event + // insertion } impl Modifier { - pub fn from_value(v: &serde_json::Value) -> Self { - let mut m = Modifier { - bold: v.find("bold").map_or(Option::None, |v| v.as_boolean()), - italic: v.find("italic").map_or(Option::None, |v| v.as_boolean()), - underlined: v.find("underlined").map_or(Option::None, |v| v.as_boolean()), - strikethrough: v.find("strikethrough").map_or(Option::None, |v| v.as_boolean()), - obfuscated: v.find("obfuscated").map_or(Option::None, |v| v.as_boolean()), - color: v.find("color").map_or(Option::None, |v| v.as_string()).map(|v| Color::from_string(&v.to_owned())), - extra: Option::None, - }; - if let Some(extra) = v.find("extra") { - if let Some(data) = extra.as_array() { - let mut ex = Vec::new(); - for e in data { - ex.push(Component::from_value(e)); - } - m.extra = Some(ex); - } - } - m - } + pub fn from_value(v: &serde_json::Value) -> Self { + let mut m = Modifier { + bold: v.find("bold").map_or(Option::None, |v| v.as_boolean()), + italic: v.find("italic").map_or(Option::None, |v| v.as_boolean()), + underlined: v.find("underlined").map_or(Option::None, |v| v.as_boolean()), + strikethrough: v.find("strikethrough").map_or(Option::None, |v| v.as_boolean()), + obfuscated: v.find("obfuscated").map_or(Option::None, |v| v.as_boolean()), + color: v.find("color").map_or(Option::None, |v| v.as_string()).map(|v| Color::from_string(&v.to_owned())), + extra: Option::None, + }; + if let Some(extra) = v.find("extra") { + if let Some(data) = extra.as_array() { + let mut ex = Vec::new(); + for e in data { + ex.push(Component::from_value(e)); + } + m.extra = Some(ex); + } + } + m + } - pub fn to_value(&self) -> serde_json::Value { - unimplemented!() - } + pub fn to_value(&self) -> serde_json::Value { + unimplemented!() + } } #[derive(Debug)] pub struct TextComponent { - pub text: String, - pub modifier: Modifier, + pub text: String, + pub modifier: Modifier, } impl TextComponent { - pub fn from_value(v: &serde_json::Value, modifier: Modifier) -> Self { - TextComponent { - text: v.find("text").unwrap().as_string().unwrap_or("").to_owned(), - modifier: modifier, - } - } + pub fn from_value(v: &serde_json::Value, modifier: Modifier) -> Self { + TextComponent { + text: v.find("text").unwrap().as_string().unwrap_or("").to_owned(), + modifier: modifier, + } + } - pub fn to_value(&self) -> serde_json::Value { - unimplemented!() - } + pub fn to_value(&self) -> serde_json::Value { + unimplemented!() + } } impl fmt::Display for TextComponent { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{}", self.text)); - if let Some(ref extra) = self.modifier.extra { - for c in extra { - try!(write!(f, "{}", c)); - } - } - Result::Ok(()) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{}", self.text)); + if let Some(ref extra) = self.modifier.extra { + for c in extra { + try!(write!(f, "{}", c)); + } + } + Result::Ok(()) + } } #[derive(Debug)] pub enum Color { - Black, - DarkBlue, - DarkGreen, - DarkAqua, - DarkRed, - DarkPurple, - Gold, - Gray, - DarkGray, - Blue, - Green, - Aqua, - Red, - LightPurple, - Yellow, - White, - RGB(u8, u8, u8) + Black, + DarkBlue, + DarkGreen, + DarkAqua, + DarkRed, + DarkPurple, + Gold, + Gray, + DarkGray, + Blue, + Green, + Aqua, + Red, + LightPurple, + Yellow, + White, + RGB(u8, u8, u8) } impl fmt::Display for Color { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_string()) + } } impl Color { - fn from_string(val: &String) -> Self { - match val.as_ref() { - "black" => Color::Black, - "dark_blue" => Color::DarkBlue, - "dark_green" => Color::DarkGreen, - "dark_aqua" => Color::DarkAqua, - "dark_red" => Color::DarkRed, - "dark_purple" => Color::DarkPurple, - "gold" => Color::Gold, - "gray" => Color::Gray, - "dark_gray" => Color::DarkGray, - "blue" => Color::Blue, - "green" => Color::Green, - "aqua" => Color::Aqua, - "red" => Color::Red, - "light_purple" => Color::LightPurple, - "yellow" => Color::Yellow, - "white" => Color::White, - val if val.len() == 7 && val.as_bytes()[0] == b'#' => { - let r = match u8::from_str_radix(&val[1..3], 16) { - Ok(r) => r, - Err(_) => return Color::White, - }; - let g = match u8::from_str_radix(&val[3..5], 16) { - Ok(g) => g, - Err(_) => return Color::White, - }; - let b = match u8::from_str_radix(&val[5..7], 16) { - Ok(b) => b, - Err(_) => return Color::White, - }; - Color::RGB( - r, - g, - b - ) - } - _ => Color::White, - } - } + fn from_string(val: &String) -> Self { + match val.as_ref() { + "black" => Color::Black, + "dark_blue" => Color::DarkBlue, + "dark_green" => Color::DarkGreen, + "dark_aqua" => Color::DarkAqua, + "dark_red" => Color::DarkRed, + "dark_purple" => Color::DarkPurple, + "gold" => Color::Gold, + "gray" => Color::Gray, + "dark_gray" => Color::DarkGray, + "blue" => Color::Blue, + "green" => Color::Green, + "aqua" => Color::Aqua, + "red" => Color::Red, + "light_purple" => Color::LightPurple, + "yellow" => Color::Yellow, + "white" => Color::White, + val if val.len() == 7 && val.as_bytes()[0] == b'#' => { + let r = match u8::from_str_radix(&val[1..3], 16) { + Ok(r) => r, + Err(_) => return Color::White, + }; + let g = match u8::from_str_radix(&val[3..5], 16) { + Ok(g) => g, + Err(_) => return Color::White, + }; + let b = match u8::from_str_radix(&val[5..7], 16) { + Ok(b) => b, + Err(_) => return Color::White, + }; + Color::RGB( + r, + g, + b + ) + } + _ => Color::White, + } + } - fn to_string(&self) -> String { - match *self { - Color::Black => "black".to_owned(), - Color::DarkBlue => "dark_blue".to_owned(), - Color::DarkGreen => "dark_green".to_owned(), - Color::DarkAqua => "dark_aqua".to_owned(), - Color::DarkRed => "dark_red".to_owned(), - Color::DarkPurple => "dark_purple".to_owned(), - Color::Gold => "gold".to_owned(), - Color::Gray => "gray".to_owned(), - Color::DarkGray => "dark_gray".to_owned(), - Color::Blue => "blue".to_owned(), - Color::Green => "green".to_owned(), - Color::Aqua => "aqua".to_owned(), - Color::Red => "red".to_owned(), - Color::LightPurple => "light_purple".to_owned(), - Color::Yellow => "yellow".to_owned(), - Color::White => "white".to_owned(), - Color::RGB(r, g, b) => format!("#{:02X}{:02X}{:02X}", r, g, b), - } - } + fn to_string(&self) -> String { + match *self { + Color::Black => "black".to_owned(), + Color::DarkBlue => "dark_blue".to_owned(), + Color::DarkGreen => "dark_green".to_owned(), + Color::DarkAqua => "dark_aqua".to_owned(), + Color::DarkRed => "dark_red".to_owned(), + Color::DarkPurple => "dark_purple".to_owned(), + Color::Gold => "gold".to_owned(), + Color::Gray => "gray".to_owned(), + Color::DarkGray => "dark_gray".to_owned(), + Color::Blue => "blue".to_owned(), + Color::Green => "green".to_owned(), + Color::Aqua => "aqua".to_owned(), + Color::Red => "red".to_owned(), + Color::LightPurple => "light_purple".to_owned(), + Color::Yellow => "yellow".to_owned(), + Color::White => "white".to_owned(), + Color::RGB(r, g, b) => format!("#{:02X}{:02X}{:02X}", r, g, b), + } + } - #[allow(dead_code)] - fn to_rgb(&self) -> (u8, u8, u8) { - match *self { - Color::Black =>(0, 0, 0), - Color::DarkBlue =>(0, 0, 170), - Color::DarkGreen =>(0, 170, 0), - Color::DarkAqua =>(0, 170, 170), - Color::DarkRed =>(170, 0, 0), - Color::DarkPurple =>(170, 0, 170), - Color::Gold =>(255, 170, 0), - Color::Gray =>(170, 170, 170), - Color::DarkGray =>(85, 85, 85), - Color::Blue =>(85, 85, 255), - Color::Green =>(85, 255, 85), - Color::Aqua =>(85, 255, 255), - Color::Red =>(255, 85, 85), - Color::LightPurple =>(255, 85, 255), - Color::Yellow =>(255, 255, 85), - Color::White =>(255, 255, 255), - Color::RGB(r, g, b) => (r, g, b), - } - } + #[allow(dead_code)] + fn to_rgb(&self) -> (u8, u8, u8) { + match *self { + Color::Black =>(0, 0, 0), + Color::DarkBlue =>(0, 0, 170), + Color::DarkGreen =>(0, 170, 0), + Color::DarkAqua =>(0, 170, 170), + Color::DarkRed =>(170, 0, 0), + Color::DarkPurple =>(170, 0, 170), + Color::Gold =>(255, 170, 0), + Color::Gray =>(170, 170, 170), + Color::DarkGray =>(85, 85, 85), + Color::Blue =>(85, 85, 255), + Color::Green =>(85, 255, 85), + Color::Aqua =>(85, 255, 255), + Color::Red =>(255, 85, 85), + Color::LightPurple =>(255, 85, 255), + Color::Yellow =>(255, 255, 85), + Color::White =>(255, 255, 255), + Color::RGB(r, g, b) => (r, g, b), + } + } } #[test] fn test_color_from() { - let test = Color::from_string(&"#FF0000".to_owned()); - match test { - Color::RGB(r, g, b) => assert!(r == 255 && g == 0 && b == 0), - _ => panic!("Wrong type"), - } - let test = Color::from_string(&"#123456".to_owned()); - match test { - Color::RGB(r, g, b) => assert!(r == 0x12 && g == 0x34 && b == 0x56), - _ => panic!("Wrong type"), - } - let test = Color::from_string(&"red".to_owned()); - match test { - Color::Red => {}, - _ => panic!("Wrong type"), - } - let test = Color::from_string(&"dark_blue".to_owned()); - match test { - Color::DarkBlue => {}, - _ => panic!("Wrong type"), - } + let test = Color::from_string(&"#FF0000".to_owned()); + match test { + Color::RGB(r, g, b) => assert!(r == 255 && g == 0 && b == 0), + _ => panic!("Wrong type"), + } + let test = Color::from_string(&"#123456".to_owned()); + match test { + Color::RGB(r, g, b) => assert!(r == 0x12 && g == 0x34 && b == 0x56), + _ => panic!("Wrong type"), + } + let test = Color::from_string(&"red".to_owned()); + match test { + Color::Red => {}, + _ => panic!("Wrong type"), + } + let test = Color::from_string(&"dark_blue".to_owned()); + match test { + Color::DarkBlue => {}, + _ => panic!("Wrong type"), + } } From 2d10d38e4c272adef624d4a5a15c776a882f3b07 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Sat, 12 Sep 2015 20:31:26 +0100 Subject: [PATCH 03/47] Complete protocol implementation --- protocol/src/format.rs | 10 +- protocol/src/item.rs | 54 +++++ protocol/src/nbt/mod.rs | 274 ++++++++++++++++++++++++ protocol/src/types/blockpos.rs | 54 +++++ protocol/src/types/metadata.rs | 380 +++++++++++++++++++++++++++++++++ protocol/src/types/mod.rs | 6 + 6 files changed, 772 insertions(+), 6 deletions(-) create mode 100644 protocol/src/item.rs create mode 100644 protocol/src/nbt/mod.rs create mode 100644 protocol/src/types/blockpos.rs create mode 100644 protocol/src/types/metadata.rs create mode 100644 protocol/src/types/mod.rs diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 7928967..26ec1e7 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -4,8 +4,7 @@ use std::fmt; #[derive(Debug)] pub enum Component { - Text(TextComponent), - None + Text(TextComponent) } impl Component { @@ -16,7 +15,7 @@ impl Component { } else if v.find("text").is_some(){ Component::Text(TextComponent::from_value(v, modifier)) } else { - Component::None + Component::Text(TextComponent{text: "".to_owned(), modifier: modifier}) } } @@ -29,18 +28,17 @@ impl fmt::Display for Component { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Component::Text(ref txt) => write!(f, "{}", txt), - Component::None => Result::Ok(()), } } } impl Default for Component { fn default() -> Self { - Component::None + Component::Text(TextComponent{text: "".to_owned(), modifier: Default::default()}) } } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Modifier { pub extra: Option>, pub bold: Option, diff --git a/protocol/src/item.rs b/protocol/src/item.rs new file mode 100644 index 0000000..27661f2 --- /dev/null +++ b/protocol/src/item.rs @@ -0,0 +1,54 @@ +extern crate byteorder; + +use nbt; +use protocol::{Serializable}; +use std::io; +use std::io::{Read, Write}; +use self::byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; + +#[derive(Debug)] +pub struct Stack { + id: isize, + count: isize, + damage: isize, + tag: Option, +} + + +impl Default for Stack { + fn default() -> Stack { + Stack { + id: -1, + count: 0, + damage: 0, + tag: None, + } + } +} + +impl Serializable for Option { + fn read_from(buf: &mut io::Read) -> Result, io::Error> { + let id = try!(buf.read_i16::()); + if id == -1 { + return Ok(None); + } + Ok(Some(Stack{ + id: id as isize, + count: try!(buf.read_u8()) as isize, + damage: try!(buf.read_i16::()) as isize, + tag: try!(Serializable::read_from(buf)), + })) + } + fn write_to(&self, buf: &mut io::Write) -> Result<(), io::Error> { + match *self { + Some(ref val) => { + try!(buf.write_i16::(val.id as i16)); + try!(buf.write_u8(val.count as u8)); + try!(buf.write_i16::(val.damage as i16)); + try!(val.tag.write_to(buf)); + }, + None => try!(buf.write_i16::(-1)), + } + Result::Ok(()) + } +} diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs new file mode 100644 index 0000000..7abfd9e --- /dev/null +++ b/protocol/src/nbt/mod.rs @@ -0,0 +1,274 @@ +extern crate byteorder; + +use std::collections::HashMap; +use std::io; +use std::io::{Read, Write}; + +use super::protocol::{Serializable}; +use super::protocol; +use self::byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; + +#[derive(Debug)] +pub enum Tag { + End, + Byte(i8), + Short(i16), + Int(i32), + Long(i64), + Float(f32), + Double(f64), + ByteArray(Vec), + String(String), + List(Vec), + Compound(HashMap), + IntArray(Vec), +} + +#[derive(Debug)] +pub struct NamedTag(pub String, pub Tag); + +impl Tag { + + pub fn new_compound() -> Tag { + Tag::Compound(HashMap::new()) + } + + pub fn new_list() -> Tag { + Tag::List(Vec::new()) + } + + /// Returns the tag with the given name from the compound. + /// + /// # Panics + /// Panics when the tag isn't a compound. + pub fn get(&self, name: &str) -> Option<&Tag> { + match *self { + Tag::Compound(ref val) => val.get(name), + _ => panic!("not a compound tag"), + } + } + + /// Places the tag into the compound using the given name. + /// + /// # Panics + /// Panics when the tag isn't a compound. + pub fn put(&mut self, name: &str, tag: Tag) { + match *self { + Tag::Compound(ref mut val) => val.insert(name.to_owned(), tag), + _ => panic!("not a compound tag"), + }; + } + + pub fn is_compound(&self) -> bool { + match *self { + Tag::Compound(_) => true, + _ => false, + } + } + + pub fn as_byte(&self) -> Option { + match *self { + Tag::Byte(val) => Some(val), + _ => None, + } + } + + pub fn as_short(&self) -> Option { + match *self { + Tag::Short(val) => Some(val), + _ => None, + } + } + + pub fn as_int(&self) -> Option { + match *self { + Tag::Int(val) => Some(val), + _ => None, + } + } + + pub fn as_long(&self) -> Option { + match *self { + Tag::Long(val) => Some(val), + _ => None, + } + } + + pub fn as_float(&self) -> Option { + match *self { + Tag::Float(val) => Some(val), + _ => None, + } + } + + pub fn as_double(&self) -> Option { + match *self { + Tag::Double(val) => Some(val), + _ => None, + } + } + + pub fn as_byte_array(&self) -> Option<&[u8]> { + match *self { + Tag::ByteArray(ref val) => Some(&val[..]), + _ => None, + } + } + + pub fn as_string(&self) -> Option<&str> { + match *self { + Tag::String(ref val) => Some(&val[..]), + _ => None, + } + } + + pub fn as_list(&self) -> Option<&[Tag]> { + match *self { + Tag::List(ref val) => Some(&val[..]), + _ => None, + } + } + + pub fn as_compound(&self) -> Option<&HashMap> { + match *self { + Tag::Compound(ref val) => Some(val), + _ => None, + } + } + + pub fn as_int_array(&self) -> Option<&[i32]> { + match *self { + Tag::IntArray(ref val) => Some(&val[..]), + _ => None, + } + } + + fn internal_id(&self) -> u8 { + match *self { + Tag::End => 0, + Tag::Byte(_) => 1, + Tag::Short(_) => 2, + Tag::Int(_) => 3, + Tag::Long(_) => 4, + Tag::Float(_) => 5, + Tag::Double(_) => 6, + Tag::ByteArray(_) => 7, + Tag::String(_) => 8, + Tag::List(_) => 9, + Tag::Compound(_) => 10, + Tag::IntArray(_) => 11, + } + } + + fn read_type(id: u8, buf: &mut io::Read) -> Result { + match id { + 0 => unreachable!(), + 1 => Ok(Tag::Byte(try!(buf.read_i8()))), + 2 => Ok(Tag::Short(try!(buf.read_i16::()))), + 3 => Ok(Tag::Int(try!(buf.read_i32::()))), + 4 => Ok(Tag::Long(try!(buf.read_i64::()))), + 5 => Ok(Tag::Float(try!(buf.read_f32::()))), + 6 => Ok(Tag::Double(try!(buf.read_f64::()))), + 7 => Ok(Tag::ByteArray({ + let len : i32 = try!(Serializable::read_from(buf)); + let mut data = Vec::with_capacity(len as usize); + try!(buf.take(len as u64).read_to_end(&mut data)); + data + })), + 8 => Ok(Tag::String(try!(read_string(buf)))), + 9 => { + let mut l = Vec::new(); + let ty = try!(buf.read_u8()); + let len : i32 = try!(Serializable::read_from(buf)); + for _ in 0 .. len { + l.push(try!(Tag::read_type(ty, buf))); + } + Ok(Tag::List(l)) + }, + 10 => { + let mut c = Tag::new_compound(); + loop { + let ty = try!(buf.read_u8()); + if ty == 0 { + break; + } + let name: String = try!(read_string(buf)); + c.put(&name[..], try!(Tag::read_type(ty, buf))); + } + Ok(c) + }, + 11 => Ok(Tag::IntArray({ + let len : i32 = try!(Serializable::read_from(buf)); + let mut data = Vec::with_capacity(len as usize); + for _ in 0 .. len { + data.push(try!(buf.read_i32::())); + } + data + })), + _ => Err(io::Error::new(io::ErrorKind::InvalidData, protocol::Error::Err("invalid tag".to_owned()))), + } + } +} + +impl Serializable for Tag { + fn read_from(buf: &mut io::Read) -> Result { + Tag::read_type(10, buf) + } + + fn write_to(&self, buf: &mut io::Write) -> Result<(), io::Error> { + match *self { + Tag::End => {}, + Tag::Byte(val) => try!(buf.write_i8(val)), + Tag::Short(val) => try!(buf.write_i16::(val)), + Tag::Int(val) => try!(buf.write_i32::(val)), + Tag::Long(val) => try!(buf.write_i64::(val)), + Tag::Float(val) => try!(buf.write_f32::(val)), + Tag::Double(val) => try!(buf.write_f64::(val)), + Tag::ByteArray(ref val) => { + try!((val.len() as i32).write_to(buf)); + try!(buf.write_all(val)); + }, + Tag::String(ref val) => try!(write_string(buf, val)), + Tag::List(ref val) => { + if val.is_empty() { + try!(buf.write_u8(0)); + try!(buf.write_i32::(0)); + } else { + try!(buf.write_u8(val[0].internal_id())); + try!(buf.write_i32::(val.len() as i32)); + for e in val { + try!(e.write_to(buf)); + } + } + }, + Tag::Compound(ref val) => { + for (k, v) in val { + try!(v.internal_id().write_to(buf)); + try!(write_string(buf, k)); + try!(v.write_to(buf)); + } + try!(buf.write_u8(0)); + }, + Tag::IntArray(ref val) => { + try!((val.len() as i32).write_to(buf)); + for v in val { + try!(v.write_to(buf)); + } + }, + } + Result::Ok(()) + } +} + +pub fn write_string(buf: &mut io::Write, s: &String)-> io::Result<()> { + let data = s.as_bytes(); + try!((data.len() as i16).write_to(buf)); + buf.write_all(data) +} + +pub fn read_string(buf: &mut io::Read) -> io::Result { + let len: i16 = try!(buf.read_i16::()); + let mut ret = String::new(); + try!(buf.take(len as u64).read_to_string(&mut ret)); + Result::Ok(ret) +} diff --git a/protocol/src/types/blockpos.rs b/protocol/src/types/blockpos.rs new file mode 100644 index 0000000..5f71af0 --- /dev/null +++ b/protocol/src/types/blockpos.rs @@ -0,0 +1,54 @@ +extern crate byteorder; + +use std::fmt; +use protocol::{Serializable}; +use std::io; +use std::io::{Read, Write}; +use self::byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; + +#[derive(Clone, Copy)] +pub struct Position(u64); + +impl Position { + fn new(x: i32, y: i32, z: i32) -> Position { + Position( + (((x as u64) & 0x3FFFFFF) << 38) | + (((y as u64) & 0xFFF) << 26) | + ((z as u64) & 0x3FFFFFF) + ) + } + + fn get_x(&self) -> i32 { + ((self.0 as i64) >> 38) as i32 + } + + fn get_y(&self) -> i32 { + (((self.0 as i64) >> 26) & 0xFFF) as i32 + } + + fn get_z(&self) -> i32 { + ((self.0 as i64) << 38 >> 38) as i32 + } +} + +impl Default for Position { + fn default() -> Position { + Position(0) + } +} + +impl fmt::Debug for Position { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "<{},{},{}>", self.get_x(), self.get_y(), self.get_z()) + } +} + +impl Serializable for Position { + fn read_from(buf: &mut io::Read) -> Result { + Result::Ok(Position(try!(buf.read_u64::()))) + } + fn write_to(&self, buf: &mut io::Write) -> Result<(), io::Error> { + try!(buf.write_u64::(self.0)); + Result::Ok(()) + } +} diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs new file mode 100644 index 0000000..3b78b42 --- /dev/null +++ b/protocol/src/types/metadata.rs @@ -0,0 +1,380 @@ + +use std::collections::HashMap; +use std::marker::PhantomData; +use std::io; +use std::io::{Read, Write}; +use std::fmt; +use protocol; +use protocol::{Serializable}; +use format; +use item; + +pub struct MetadataKey { + index: i32, + ty: PhantomData, +} + +impl MetadataKey { + // TODO: Make const later when possible + /*const*/ fn new(index: i32) -> MetadataKey { + MetadataKey { + index: index, + ty: PhantomData, + } + } +} + +pub struct Metadata { + map: HashMap, +} + +impl Metadata { + pub fn new() -> Metadata { + Metadata { map: HashMap::new() } + } + + pub fn get(&self, key: &MetadataKey) -> Option<&T> { + self.map.get(&key.index).map(T::unwrap) + } + + pub fn put(&mut self, key: &MetadataKey, val: T) { + self.map.insert(key.index, val.wrap()); + } + + fn put_raw(&mut self, index: i32, val: T) { + self.map.insert(index, val.wrap()); + } +} + +impl Serializable for Metadata { + + fn read_from(buf: &mut io::Read) -> Result { + let mut m = Metadata::new(); + loop { + let index = try!(u8::read_from(buf)) as i32; + if index == 0xFF { + break; + } + let ty = try!(u8::read_from(buf)); + match ty { + 0 => m.put_raw(index, try!(i8::read_from(buf))), + 1 => m.put_raw(index, try!(protocol::VarInt::read_from(buf)).0), + 2 => m.put_raw(index, try!(f32::read_from(buf))), + 3 => m.put_raw(index, try!(String::read_from(buf))), + 4 => m.put_raw(index, try!(format::Component::read_from(buf))), + 5 => m.put_raw(index, try!(Option::::read_from(buf))), + 6 => m.put_raw(index, try!(bool::read_from(buf))), + 7 => m.put_raw(index, [ + try!(f32::read_from(buf)), + try!(f32::read_from(buf)), + try!(f32::read_from(buf)) + ]), + 8 => m.put_raw(index, try!(super::Position::read_from(buf))), + 9 => { + if try!(bool::read_from(buf)) { + m.put_raw(index, try!(Option::::read_from(buf))); + } else { + m.put_raw::>(index, None); + } + }, + 10 => m.put_raw(index, try!(protocol::VarInt::read_from(buf))), + 11 => { + if try!(bool::read_from(buf)) { + m.put_raw(index, try!(Option::::read_from(buf))); + } else { + m.put_raw::>(index, None); + } + }, + 12 => m.put_raw(index, try!(protocol::VarInt::read_from(buf)).0 as u16), + _ => return Err(io::Error::new(io::ErrorKind::InvalidInput, protocol::Error::Err("unknown metadata type".to_owned()))), + } + } + Ok(m) + } + + fn write_to(&self, buf: &mut io::Write) -> Result<(), io::Error> { + for (k, v) in &self.map { + try!((*k as u8).write_to(buf)); + match *v { + Value::Byte(ref val) => { + try!(u8::write_to(&0, buf)); + try!(val.write_to(buf)); + }, + Value::Int(ref val) => { + try!(u8::write_to(&1, buf)); + try!(protocol::VarInt(*val).write_to(buf)); + }, + Value::Float(ref val) => { + try!(u8::write_to(&2, buf)); + try!(val.write_to(buf)); + }, + Value::String(ref val) => { + try!(u8::write_to(&3, buf)); + try!(val.write_to(buf)); + }, + Value::FormatComponent(ref val) => { + try!(u8::write_to(&4, buf)); + try!(val.write_to(buf)); + }, + Value::OptionalItemStack(ref val) => { + try!(u8::write_to(&5, buf)); + try!(val.write_to(buf)); + }, + Value::Bool(ref val) => { + try!(u8::write_to(&6, buf)); + try!(val.write_to(buf)); + }, + Value::Vector(ref val) => { + try!(u8::write_to(&7, buf)); + try!(val[0].write_to(buf)); + try!(val[1].write_to(buf)); + try!(val[2].write_to(buf)); + }, + Value::Position(ref val) => { + try!(u8::write_to(&8, buf)); + try!(val.write_to(buf)); + }, + Value::OptionalPosition(ref val) => { + try!(u8::write_to(&9, buf)); + try!(val.is_some().write_to(buf)); + try!(val.write_to(buf)); + }, + Value::Direction(ref val) => { + try!(u8::write_to(&10, buf)); + try!(val.write_to(buf)); + } + Value::OptionalUUID(ref val) => { + try!(u8::write_to(&11, buf)); + try!(val.is_some().write_to(buf)); + try!(val.write_to(buf)); + }, + Value::Block(ref val) => { + try!(u8::write_to(&11, buf)); + try!(protocol::VarInt(*val as i32).write_to(buf)); + } + } + } + try!(u8::write_to(&0xFF, buf)); + Ok(()) + } +} + +impl fmt::Debug for Metadata { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "Metadata[ ")); + for (k, v) in &self.map { + try!(write!(f, "{:?}={:?}, ", k, v)); + } + write!(f, "]") + } +} + +impl Default for Metadata { + fn default() -> Metadata { + Metadata::new() + } +} + +#[derive(Debug)] +enum Value { + Byte(i8), + Int(i32), + Float(f32), + String(String), + FormatComponent(format::Component), + OptionalItemStack(Option), + Bool(bool), + Vector([f32; 3]), + Position(super::Position), + OptionalPosition(Option), + Direction(protocol::VarInt), // TODO: Proper type + OptionalUUID(Option), + Block(u16), // TODO: Proper type +} + +pub trait MetaValue { + fn unwrap(&Value) -> &Self; + fn wrap(self) -> Value; +} + +impl MetaValue for i8 { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Byte(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Byte(self) + } +} + +impl MetaValue for i32 { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Int(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Int(self) + } +} + +impl MetaValue for f32 { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Float(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Float(self) + } +} + +impl MetaValue for String { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::String(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::String(self) + } +} + +impl MetaValue for format::Component { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::FormatComponent(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::FormatComponent(self) + } +} + +impl MetaValue for Option { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::OptionalItemStack(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::OptionalItemStack(self) + } +} + +impl MetaValue for bool { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Bool(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Bool(self) + } +} + +impl MetaValue for [f32; 3] { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Vector(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Vector(self) + } +} + +impl MetaValue for super::Position { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Position(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Position(self) + } +} + +impl MetaValue for Option { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::OptionalPosition(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::OptionalPosition(self) + } +} + +impl MetaValue for protocol::VarInt { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Direction(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Direction(self) + } +} + +impl MetaValue for Option { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::OptionalUUID(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::OptionalUUID(self) + } +} + +impl MetaValue for u16 { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Block(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Block(self) + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::marker::PhantomData; + + const TEST: MetadataKey = + MetadataKey { + index: 0, + ty: PhantomData, + }; + + #[test] + fn basic() { + let mut m = Metadata::new(); + + m.put(&TEST, "Hello world".to_owned()); + + match m.get(&TEST) { + Some(val) => { + assert!(val == "Hello world"); + } + None => panic!("failed"), + } + } +} diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs new file mode 100644 index 0000000..082cb1a --- /dev/null +++ b/protocol/src/types/mod.rs @@ -0,0 +1,6 @@ + +mod blockpos; +pub use self::blockpos::*; + +mod metadata; +pub use self::metadata::*; From b9d7063099ef031861cea60fe9328009737872a7 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Thu, 17 Sep 2015 16:04:25 +0100 Subject: [PATCH 04/47] Base of ui complete --- protocol/src/format.rs | 2 +- protocol/src/item.rs | 3 +-- protocol/src/nbt/mod.rs | 3 +-- protocol/src/types/metadata.rs | 1 + 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 26ec1e7..8cef4af 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -1,5 +1,5 @@ -extern crate serde_json; +use serde_json; use std::fmt; #[derive(Debug)] diff --git a/protocol/src/item.rs b/protocol/src/item.rs index 27661f2..2cdd046 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -1,10 +1,9 @@ -extern crate byteorder; use nbt; use protocol::{Serializable}; use std::io; use std::io::{Read, Write}; -use self::byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; +use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; #[derive(Debug)] pub struct Stack { diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index 7abfd9e..9bfd5f7 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -1,4 +1,3 @@ -extern crate byteorder; use std::collections::HashMap; use std::io; @@ -6,7 +5,7 @@ use std::io::{Read, Write}; use super::protocol::{Serializable}; use super::protocol; -use self::byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; +use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; #[derive(Debug)] pub enum Tag { diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 3b78b42..7ad261e 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -15,6 +15,7 @@ pub struct MetadataKey { } impl MetadataKey { + #[allow(dead_code)] // TODO: Make const later when possible /*const*/ fn new(index: i32) -> MetadataKey { MetadataKey { From 906a44d9d43a523e5593a547ee085b0d9656dcae Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Thu, 17 Sep 2015 16:21:56 +0100 Subject: [PATCH 05/47] Add license --- protocol/src/format.rs | 13 +++++++++++++ protocol/src/item.rs | 13 +++++++++++++ protocol/src/nbt/mod.rs | 13 +++++++++++++ protocol/src/types/blockpos.rs | 14 ++++++++++++++ protocol/src/types/metadata.rs | 13 +++++++++++++ protocol/src/types/mod.rs | 13 +++++++++++++ 6 files changed, 79 insertions(+) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 8cef4af..d68d7a6 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -1,3 +1,16 @@ +// Copyright 2015 Matthew Collins +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use serde_json; use std::fmt; diff --git a/protocol/src/item.rs b/protocol/src/item.rs index 2cdd046..5f143ad 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -1,3 +1,16 @@ +// Copyright 2015 Matthew Collins +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use nbt; use protocol::{Serializable}; diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index 9bfd5f7..4100448 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -1,3 +1,16 @@ +// Copyright 2015 Matthew Collins +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::collections::HashMap; use std::io; diff --git a/protocol/src/types/blockpos.rs b/protocol/src/types/blockpos.rs index 5f71af0..7e36c55 100644 --- a/protocol/src/types/blockpos.rs +++ b/protocol/src/types/blockpos.rs @@ -1,3 +1,17 @@ +// Copyright 2015 Matthew Collins +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + extern crate byteorder; use std::fmt; diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 7ad261e..f4281b6 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -1,3 +1,16 @@ +// Copyright 2015 Matthew Collins +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. use std::collections::HashMap; use std::marker::PhantomData; diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index 082cb1a..681b872 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -1,3 +1,16 @@ +// Copyright 2015 Matthew Collins +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. mod blockpos; pub use self::blockpos::*; From 63731ca4503c2d1e76efb81c8a8ee4a162c43ed0 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Mon, 21 Sep 2015 13:08:06 +0100 Subject: [PATCH 06/47] Basic logo work --- protocol/src/types/bit/map.rs | 90 +++++++++++++++++++++++++++++++++++ protocol/src/types/bit/mod.rs | 19 ++++++++ protocol/src/types/bit/set.rs | 56 ++++++++++++++++++++++ protocol/src/types/mod.rs | 2 + 4 files changed, 167 insertions(+) create mode 100644 protocol/src/types/bit/map.rs create mode 100644 protocol/src/types/bit/mod.rs create mode 100644 protocol/src/types/bit/set.rs diff --git a/protocol/src/types/bit/map.rs b/protocol/src/types/bit/map.rs new file mode 100644 index 0000000..8d289c0 --- /dev/null +++ b/protocol/src/types/bit/map.rs @@ -0,0 +1,90 @@ +// Copyright 2015 Matthew Collins +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub struct Map { + bits: Vec, + bit_size: usize, + length: usize +} + +#[test] +fn test_map() { + let mut map = Map::new(4096, 4); + for i in 0 .. 4096 { + for j in 0 .. 16 { + map.set(i, j); + if map.get(i) != j { + panic!("Fail"); + } + } + } +} + +#[test] +fn test_map_odd() { + for size in 1 .. 16 { + let mut map = Map::new(64*3, size); + let max = (1 << size) - 1; + for i in 0 .. 64*3 { + for j in 0 .. max { + map.set(i, j); + if map.get(i) != j { + panic!("Index: {} wanted {} and got {}", i, j, map.get(i)); + } + } + } + } +} + +impl Map { + pub fn new(len: usize, size: usize) -> Map { + let mut map = Map { + bit_size: size, + length: len, + bits: Vec::with_capacity((len*size)/64) + }; + for _ in 0 .. len { + map.bits.push(0) + } + map + } + + pub fn set(&mut self, i: usize, val: usize) { + let i = i * self.bit_size; + let pos = i / 64; + let mask = (1 << self.bit_size) - 1; + let ii = i % 64; + self.bits[pos] = (self.bits[pos] & !(mask << ii )) | ((val << ii) as u64); + let pos2 = (i + self.bit_size - 1) / 64; + if pos2 != pos { + let used = 64 - ii; + let rem = self.bit_size - used; + self.bits[pos2] = self.bits[pos2] >> rem << rem | (val as u64 >> used); + } + } + + pub fn get(&mut self, i: usize) -> usize { + let i = i * self.bit_size; + let pos = i / 64; + let mask = (1 << self.bit_size) - 1; + let ii = i % 64; + let pos2 = (i + self.bit_size - 1) / 64; + if pos2 != pos { + let used = 64 - ii; + (((self.bits[pos] >> ii) | (self.bits[pos2] << used)) & mask) as usize + } else { + ((self.bits[pos] >> ii) & mask) as usize + } + } +} diff --git a/protocol/src/types/bit/mod.rs b/protocol/src/types/bit/mod.rs new file mode 100644 index 0000000..bc345c6 --- /dev/null +++ b/protocol/src/types/bit/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2015 Matthew Collins +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub mod set; +pub mod map; + +pub use self::set::Set; +pub use self::map::Map; diff --git a/protocol/src/types/bit/set.rs b/protocol/src/types/bit/set.rs new file mode 100644 index 0000000..995ce69 --- /dev/null +++ b/protocol/src/types/bit/set.rs @@ -0,0 +1,56 @@ +// Copyright 2015 Matthew Collins +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub struct Set { + data : Vec +} + +#[test] +fn test_set() { + let mut set = Set::new(200); + for i in 0 .. 200 { + if i % 3 == 0 { + set.set(i, true) + } + } + for i in 0 .. 200 { + if set.get(i) != (i%3 == 0) { + panic!("Fail") + } + } +} + +impl Set { + pub fn new(size: usize) -> Set { + let mut set = Set { + data: Vec::with_capacity(size) + }; + for _ in 0 .. size { + set.data.push(0) + } + set + } + + pub fn set(&mut self, i: usize, v: bool) { + if v { + self.data[i>>6] |= 1 << (i & 0x3F) + } else { + self.data[i>>6] &= !(1 << (i & 0x3F)) + } + } + + pub fn get(&mut self, i: usize) -> bool { + return (self.data[i>>6] & (1 << (i & 0x3F))) != 0 + } +} diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index 681b872..034015f 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -17,3 +17,5 @@ pub use self::blockpos::*; mod metadata; pub use self::metadata::*; + +pub mod bit; \ No newline at end of file From 1920e9e9e27d7538e443b10920c18fb31fe33be7 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Wed, 23 Sep 2015 20:16:25 +0100 Subject: [PATCH 07/47] Base of server list --- protocol/src/format.rs | 103 ++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index d68d7a6..6cbe786 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -15,26 +15,27 @@ use serde_json; use std::fmt; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Component { Text(TextComponent) } impl Component { - pub fn from_value(v: &serde_json::Value) -> Self { - let modifier = Modifier::from_value(v); - if let Some(val) = v.as_string() { - Component::Text(TextComponent{text: val.to_owned(), modifier: modifier}) - } else if v.find("text").is_some(){ - Component::Text(TextComponent::from_value(v, modifier)) - } else { - Component::Text(TextComponent{text: "".to_owned(), modifier: modifier}) - } + pub fn from_value(v: &serde_json::Value) -> Self { + let mut modifier = Modifier::from_value(v); + if let Some(val) = v.as_string() { + Component::Text(TextComponent{text: val.to_owned(), modifier: modifier}) + } else if v.find("text").is_some(){ + Component::Text(TextComponent::from_value(v, modifier)) + } else { + modifier.color = Some(Color::RGB(255, 0, 0)); + Component::Text(TextComponent{text: "UNHANDLED".to_owned(), modifier: modifier}) } + } - pub fn to_value(&self) -> serde_json::Value { - unimplemented!() - } + pub fn to_value(&self) -> serde_json::Value { + unimplemented!() + } } impl fmt::Display for Component { @@ -51,7 +52,7 @@ impl Default for Component { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct Modifier { pub extra: Option>, pub bold: Option, @@ -67,50 +68,59 @@ pub struct Modifier { } impl Modifier { - pub fn from_value(v: &serde_json::Value) -> Self { - let mut m = Modifier { - bold: v.find("bold").map_or(Option::None, |v| v.as_boolean()), - italic: v.find("italic").map_or(Option::None, |v| v.as_boolean()), - underlined: v.find("underlined").map_or(Option::None, |v| v.as_boolean()), - strikethrough: v.find("strikethrough").map_or(Option::None, |v| v.as_boolean()), - obfuscated: v.find("obfuscated").map_or(Option::None, |v| v.as_boolean()), - color: v.find("color").map_or(Option::None, |v| v.as_string()).map(|v| Color::from_string(&v.to_owned())), - extra: Option::None, - }; - if let Some(extra) = v.find("extra") { - if let Some(data) = extra.as_array() { - let mut ex = Vec::new(); - for e in data { - ex.push(Component::from_value(e)); - } - m.extra = Some(ex); + pub fn from_value(v: &serde_json::Value) -> Self { + let mut m = Modifier { + bold: v.find("bold").map_or(Option::None, |v| v.as_boolean()), + italic: v.find("italic").map_or(Option::None, |v| v.as_boolean()), + underlined: v.find("underlined").map_or(Option::None, |v| v.as_boolean()), + strikethrough: v.find("strikethrough").map_or(Option::None, |v| v.as_boolean()), + obfuscated: v.find("obfuscated").map_or(Option::None, |v| v.as_boolean()), + color: v.find("color").map_or(Option::None, |v| v.as_string()).map(|v| Color::from_string(&v.to_owned())), + extra: Option::None, + }; + if let Some(extra) = v.find("extra") { + if let Some(data) = extra.as_array() { + let mut ex = Vec::new(); + for e in data { + ex.push(Component::from_value(e)); } + m.extra = Some(ex); } - m } + m + } - pub fn to_value(&self) -> serde_json::Value { - unimplemented!() - } + pub fn to_value(&self) -> serde_json::Value { + unimplemented!() + } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct TextComponent { pub text: String, - pub modifier: Modifier, + pub modifier: Modifier, } impl TextComponent { - pub fn from_value(v: &serde_json::Value, modifier: Modifier) -> Self { - TextComponent { - text: v.find("text").unwrap().as_string().unwrap_or("").to_owned(), - modifier: modifier, + pub fn new(val: &str) -> TextComponent { + TextComponent { + text: val.to_owned(), + modifier: Modifier { + .. Default::default() } } + } - pub fn to_value(&self) -> serde_json::Value { - unimplemented!() + pub fn from_value(v: &serde_json::Value, modifier: Modifier) -> Self { + TextComponent { + text: v.find("text").unwrap().as_string().unwrap_or("").to_owned(), + modifier: modifier, } + } + + pub fn to_value(&self) -> serde_json::Value { + unimplemented!() + } } impl fmt::Display for TextComponent { @@ -125,7 +135,7 @@ impl fmt::Display for TextComponent { } } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum Color { Black, DarkBlue, @@ -194,7 +204,7 @@ impl Color { } } - fn to_string(&self) -> String { + pub fn to_string(&self) -> String { match *self { Color::Black => "black".to_owned(), Color::DarkBlue => "dark_blue".to_owned(), @@ -216,8 +226,7 @@ impl Color { } } - #[allow(dead_code)] - fn to_rgb(&self) -> (u8, u8, u8) { + pub fn to_rgb(&self) -> (u8, u8, u8) { match *self { Color::Black =>(0, 0, 0), Color::DarkBlue =>(0, 0, 170), From 12847e9686b62deca376e2678a4cf5476ed896f9 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Fri, 25 Sep 2015 14:00:49 +0100 Subject: [PATCH 08/47] Kinda functional server list --- protocol/src/format.rs | 83 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 6cbe786..f0c9cba 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -14,6 +14,7 @@ use serde_json; use std::fmt; +use std::mem; #[derive(Debug, Clone)] pub enum Component { @@ -272,3 +273,85 @@ fn test_color_from() { _ => panic!("Wrong type"), } } + +const LEGACY_CHAR: char = '§'; + +pub fn convert_legacy(c: &mut Component) { + match c { + &mut Component::Text(ref mut txt) => { + if let Some(ref mut extra) = txt.modifier.extra.as_mut() { + for e in extra.iter_mut() { + convert_legacy(e); + } + } + if txt.text.contains(LEGACY_CHAR) { + let mut parts = Vec::new(); + let mut last = 0; + let mut current = TextComponent::new(""); + { + let mut iter = txt.text.char_indices(); + while let Some((i, c)) = iter.next() { + if c == LEGACY_CHAR { + let next = match iter.next() { + Some(val) => val, + None => break, + }; + let color_char = next.1.to_lowercase().next().unwrap(); + current.text = txt.text[last .. i].to_owned(); + last = next.0 + 1; + + let mut modifier = if (color_char >= 'a' && color_char <= 'f') || (color_char >= '0' && color_char <= '9') { + Default::default() + } else { + current.modifier.clone() + }; + + let new = TextComponent::new(""); + parts.push(Component::Text(mem::replace(&mut current, new))); + + match color_char { + '0' => modifier.color = Some(Color::Black), + '1' => modifier.color = Some(Color::DarkBlue), + '2' => modifier.color = Some(Color::DarkGreen), + '3' => modifier.color = Some(Color::DarkAqua), + '4' => modifier.color = Some(Color::DarkRed), + '5' => modifier.color = Some(Color::DarkPurple), + '6' => modifier.color = Some(Color::Gold), + '7' => modifier.color = Some(Color::Gray), + '8' => modifier.color = Some(Color::DarkGray), + '9' => modifier.color = Some(Color::Blue), + 'a' => modifier.color = Some(Color::Green), + 'b' => modifier.color = Some(Color::Aqua), + 'c' => modifier.color = Some(Color::Red), + 'd' => modifier.color = Some(Color::LightPurple), + 'e' => modifier.color = Some(Color::Yellow), + 'f' => modifier.color = Some(Color::White), + 'k' => modifier.obfuscated = Some(true), + 'l' => modifier.bold = Some(true), + 'm' => modifier.strikethrough = Some(true), + 'n' => modifier.underlined = Some(true), + 'o' => modifier.italic = Some(true), + 'r' => {}, + _ => unimplemented!(), + } + + current.modifier = modifier; + } + } + } + if last < txt.text.len() { + current.text = txt.text[last..].to_owned(); + parts.push(Component::Text(current)); + } + + let old = mem::replace(&mut txt.modifier.extra, Some(parts)); + if let Some(old_extra) = old { + if let Some(ref mut extra) = txt.modifier.extra.as_mut() { + extra.extend(old_extra); + } + } + txt.text = "".to_owned(); + } + }, + } +} \ No newline at end of file From 70a3683df2a11fb03319078c27c7b0bb72f061d1 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Fri, 25 Sep 2015 15:20:55 +0100 Subject: [PATCH 09/47] Clean up --- protocol/src/types/bit/map.rs | 10 +++++++++- protocol/src/types/blockpos.rs | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/protocol/src/types/bit/map.rs b/protocol/src/types/bit/map.rs index 8d289c0..b1b9e05 100644 --- a/protocol/src/types/bit/map.rs +++ b/protocol/src/types/bit/map.rs @@ -60,6 +60,14 @@ impl Map { map } + pub fn resize(self, size: usize) -> Map { + let mut n = Map::new(self.length, size); + for i in 0 .. self.length { + n.set(i, self.get(i)); + } + n + } + pub fn set(&mut self, i: usize, val: usize) { let i = i * self.bit_size; let pos = i / 64; @@ -74,7 +82,7 @@ impl Map { } } - pub fn get(&mut self, i: usize) -> usize { + pub fn get(&self, i: usize) -> usize { let i = i * self.bit_size; let pos = i / 64; let mask = (1 << self.bit_size) - 1; diff --git a/protocol/src/types/blockpos.rs b/protocol/src/types/blockpos.rs index 7e36c55..cc38604 100644 --- a/protocol/src/types/blockpos.rs +++ b/protocol/src/types/blockpos.rs @@ -24,6 +24,7 @@ use self::byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; pub struct Position(u64); impl Position { + #[allow(dead_code)] fn new(x: i32, y: i32, z: i32) -> Position { Position( (((x as u64) & 0x3FFFFFF) << 38) | From dc810c15dd49c9b2b1ce17195b8d4bc4bf5277a4 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Tue, 29 Sep 2015 20:09:36 +0100 Subject: [PATCH 10/47] Tidy up --- protocol/src/format.rs | 4 ++-- protocol/src/types/bit/set.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index f0c9cba..50dc3f9 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -277,8 +277,8 @@ fn test_color_from() { const LEGACY_CHAR: char = '§'; pub fn convert_legacy(c: &mut Component) { - match c { - &mut Component::Text(ref mut txt) => { + match *c { + Component::Text(ref mut txt) => { if let Some(ref mut extra) = txt.modifier.extra.as_mut() { for e in extra.iter_mut() { convert_legacy(e); diff --git a/protocol/src/types/bit/set.rs b/protocol/src/types/bit/set.rs index 995ce69..e74f6c5 100644 --- a/protocol/src/types/bit/set.rs +++ b/protocol/src/types/bit/set.rs @@ -51,6 +51,6 @@ impl Set { } pub fn get(&mut self, i: usize) -> bool { - return (self.data[i>>6] & (1 << (i & 0x3F))) != 0 + (self.data[i>>6] & (1 << (i & 0x3F))) != 0 } } From 35306c62e1852c2599c3a05c82ed93eb0cb00a4e Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Wed, 7 Oct 2015 19:36:59 +0100 Subject: [PATCH 11/47] Reformat using rustfmt --- protocol/src/format.rs | 88 ++++++++++++----------- protocol/src/item.rs | 6 +- protocol/src/nbt/mod.rs | 123 +++++++++++++++++---------------- protocol/src/types/bit/map.rs | 22 +++--- protocol/src/types/bit/set.rs | 20 +++--- protocol/src/types/blockpos.rs | 9 +-- protocol/src/types/metadata.rs | 49 ++++++------- protocol/src/types/mod.rs | 2 +- 8 files changed, 160 insertions(+), 159 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 50dc3f9..49c12ba 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -18,19 +18,25 @@ use std::mem; #[derive(Debug, Clone)] pub enum Component { - Text(TextComponent) + Text(TextComponent), } impl Component { pub fn from_value(v: &serde_json::Value) -> Self { let mut modifier = Modifier::from_value(v); if let Some(val) = v.as_string() { - Component::Text(TextComponent{text: val.to_owned(), modifier: modifier}) - } else if v.find("text").is_some(){ + Component::Text(TextComponent { + text: val.to_owned(), + modifier: modifier, + }) + } else if v.find("text").is_some() { Component::Text(TextComponent::from_value(v, modifier)) } else { modifier.color = Some(Color::RGB(255, 0, 0)); - Component::Text(TextComponent{text: "UNHANDLED".to_owned(), modifier: modifier}) + Component::Text(TextComponent { + text: "UNHANDLED".to_owned(), + modifier: modifier, + }) } } @@ -49,7 +55,10 @@ impl fmt::Display for Component { impl Default for Component { fn default() -> Self { - Component::Text(TextComponent{text: "".to_owned(), modifier: Default::default()}) + Component::Text(TextComponent { + text: "".to_owned(), + modifier: Default::default(), + }) } } @@ -62,12 +71,10 @@ pub struct Modifier { pub strikethrough: Option, pub obfuscated: Option, pub color: Option, - - // click_event - // hover_event - // insertion } +// TODO: Missing events click/hover/insert + impl Modifier { pub fn from_value(v: &serde_json::Value) -> Self { let mut m = Modifier { @@ -76,7 +83,9 @@ impl Modifier { underlined: v.find("underlined").map_or(Option::None, |v| v.as_boolean()), strikethrough: v.find("strikethrough").map_or(Option::None, |v| v.as_boolean()), obfuscated: v.find("obfuscated").map_or(Option::None, |v| v.as_boolean()), - color: v.find("color").map_or(Option::None, |v| v.as_string()).map(|v| Color::from_string(&v.to_owned())), + color: v.find("color") + .map_or(Option::None, |v| v.as_string()) + .map(|v| Color::from_string(&v.to_owned())), extra: Option::None, }; if let Some(extra) = v.find("extra") { @@ -106,9 +115,7 @@ impl TextComponent { pub fn new(val: &str) -> TextComponent { TextComponent { text: val.to_owned(), - modifier: Modifier { - .. Default::default() - } + modifier: Modifier { ..Default::default() }, } } @@ -154,7 +161,7 @@ pub enum Color { LightPurple, Yellow, White, - RGB(u8, u8, u8) + RGB(u8, u8, u8), } impl fmt::Display for Color { @@ -195,11 +202,7 @@ impl Color { Ok(b) => b, Err(_) => return Color::White, }; - Color::RGB( - r, - g, - b - ) + Color::RGB(r, g, b) } _ => Color::White, } @@ -229,22 +232,22 @@ impl Color { pub fn to_rgb(&self) -> (u8, u8, u8) { match *self { - Color::Black =>(0, 0, 0), - Color::DarkBlue =>(0, 0, 170), - Color::DarkGreen =>(0, 170, 0), - Color::DarkAqua =>(0, 170, 170), - Color::DarkRed =>(170, 0, 0), - Color::DarkPurple =>(170, 0, 170), - Color::Gold =>(255, 170, 0), - Color::Gray =>(170, 170, 170), - Color::DarkGray =>(85, 85, 85), - Color::Blue =>(85, 85, 255), - Color::Green =>(85, 255, 85), - Color::Aqua =>(85, 255, 255), - Color::Red =>(255, 85, 85), - Color::LightPurple =>(255, 85, 255), - Color::Yellow =>(255, 255, 85), - Color::White =>(255, 255, 255), + Color::Black => (0, 0, 0), + Color::DarkBlue => (0, 0, 170), + Color::DarkGreen => (0, 170, 0), + Color::DarkAqua => (0, 170, 170), + Color::DarkRed => (170, 0, 0), + Color::DarkPurple => (170, 0, 170), + Color::Gold => (255, 170, 0), + Color::Gray => (170, 170, 170), + Color::DarkGray => (85, 85, 85), + Color::Blue => (85, 85, 255), + Color::Green => (85, 255, 85), + Color::Aqua => (85, 255, 255), + Color::Red => (255, 85, 85), + Color::LightPurple => (255, 85, 255), + Color::Yellow => (255, 255, 85), + Color::White => (255, 255, 255), Color::RGB(r, g, b) => (r, g, b), } } @@ -264,12 +267,12 @@ fn test_color_from() { } let test = Color::from_string(&"red".to_owned()); match test { - Color::Red => {}, + Color::Red => {} _ => panic!("Wrong type"), } let test = Color::from_string(&"dark_blue".to_owned()); match test { - Color::DarkBlue => {}, + Color::DarkBlue => {} _ => panic!("Wrong type"), } } @@ -297,10 +300,11 @@ pub fn convert_legacy(c: &mut Component) { None => break, }; let color_char = next.1.to_lowercase().next().unwrap(); - current.text = txt.text[last .. i].to_owned(); + current.text = txt.text[last..i].to_owned(); last = next.0 + 1; - let mut modifier = if (color_char >= 'a' && color_char <= 'f') || (color_char >= '0' && color_char <= '9') { + let mut modifier = if (color_char >= 'a' && color_char <= 'f') || + (color_char >= '0' && color_char <= '9') { Default::default() } else { current.modifier.clone() @@ -331,7 +335,7 @@ pub fn convert_legacy(c: &mut Component) { 'm' => modifier.strikethrough = Some(true), 'n' => modifier.underlined = Some(true), 'o' => modifier.italic = Some(true), - 'r' => {}, + 'r' => {} _ => unimplemented!(), } @@ -352,6 +356,6 @@ pub fn convert_legacy(c: &mut Component) { } txt.text = "".to_owned(); } - }, + } } -} \ No newline at end of file +} diff --git a/protocol/src/item.rs b/protocol/src/item.rs index 5f143ad..a6ab829 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -13,7 +13,7 @@ // limitations under the License. use nbt; -use protocol::{Serializable}; +use protocol::Serializable; use std::io; use std::io::{Read, Write}; use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; @@ -44,7 +44,7 @@ impl Serializable for Option { if id == -1 { return Ok(None); } - Ok(Some(Stack{ + Ok(Some(Stack { id: id as isize, count: try!(buf.read_u8()) as isize, damage: try!(buf.read_i16::()) as isize, @@ -58,7 +58,7 @@ impl Serializable for Option { try!(buf.write_u8(val.count as u8)); try!(buf.write_i16::(val.damage as i16)); try!(val.tag.write_to(buf)); - }, + } None => try!(buf.write_i16::(-1)), } Result::Ok(()) diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index 4100448..32d4a64 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -16,7 +16,7 @@ use std::collections::HashMap; use std::io; use std::io::{Read, Write}; -use super::protocol::{Serializable}; +use super::protocol::Serializable; use super::protocol; use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; @@ -173,52 +173,53 @@ impl Tag { } fn read_type(id: u8, buf: &mut io::Read) -> Result { - match id { - 0 => unreachable!(), - 1 => Ok(Tag::Byte(try!(buf.read_i8()))), - 2 => Ok(Tag::Short(try!(buf.read_i16::()))), - 3 => Ok(Tag::Int(try!(buf.read_i32::()))), - 4 => Ok(Tag::Long(try!(buf.read_i64::()))), - 5 => Ok(Tag::Float(try!(buf.read_f32::()))), - 6 => Ok(Tag::Double(try!(buf.read_f64::()))), - 7 => Ok(Tag::ByteArray({ - let len : i32 = try!(Serializable::read_from(buf)); - let mut data = Vec::with_capacity(len as usize); - try!(buf.take(len as u64).read_to_end(&mut data)); - data - })), - 8 => Ok(Tag::String(try!(read_string(buf)))), - 9 => { - let mut l = Vec::new(); - let ty = try!(buf.read_u8()); - let len : i32 = try!(Serializable::read_from(buf)); - for _ in 0 .. len { - l.push(try!(Tag::read_type(ty, buf))); - } - Ok(Tag::List(l)) - }, - 10 => { - let mut c = Tag::new_compound(); - loop { - let ty = try!(buf.read_u8()); - if ty == 0 { - break; - } - let name: String = try!(read_string(buf)); - c.put(&name[..], try!(Tag::read_type(ty, buf))); - } - Ok(c) - }, - 11 => Ok(Tag::IntArray({ - let len : i32 = try!(Serializable::read_from(buf)); - let mut data = Vec::with_capacity(len as usize); - for _ in 0 .. len { - data.push(try!(buf.read_i32::())); - } - data - })), - _ => Err(io::Error::new(io::ErrorKind::InvalidData, protocol::Error::Err("invalid tag".to_owned()))), + match id { + 0 => unreachable!(), + 1 => Ok(Tag::Byte(try!(buf.read_i8()))), + 2 => Ok(Tag::Short(try!(buf.read_i16::()))), + 3 => Ok(Tag::Int(try!(buf.read_i32::()))), + 4 => Ok(Tag::Long(try!(buf.read_i64::()))), + 5 => Ok(Tag::Float(try!(buf.read_f32::()))), + 6 => Ok(Tag::Double(try!(buf.read_f64::()))), + 7 => Ok(Tag::ByteArray({ + let len: i32 = try!(Serializable::read_from(buf)); + let mut data = Vec::with_capacity(len as usize); + try!(buf.take(len as u64).read_to_end(&mut data)); + data + })), + 8 => Ok(Tag::String(try!(read_string(buf)))), + 9 => { + let mut l = Vec::new(); + let ty = try!(buf.read_u8()); + let len: i32 = try!(Serializable::read_from(buf)); + for _ in 0..len { + l.push(try!(Tag::read_type(ty, buf))); + } + Ok(Tag::List(l)) } + 10 => { + let mut c = Tag::new_compound(); + loop { + let ty = try!(buf.read_u8()); + if ty == 0 { + break; + } + let name: String = try!(read_string(buf)); + c.put(&name[..], try!(Tag::read_type(ty, buf))); + } + Ok(c) + } + 11 => Ok(Tag::IntArray({ + let len: i32 = try!(Serializable::read_from(buf)); + let mut data = Vec::with_capacity(len as usize); + for _ in 0..len { + data.push(try!(buf.read_i32::())); + } + data + })), + _ => Err(io::Error::new(io::ErrorKind::InvalidData, + protocol::Error::Err("invalid tag".to_owned()))), + } } } @@ -229,7 +230,7 @@ impl Serializable for Tag { fn write_to(&self, buf: &mut io::Write) -> Result<(), io::Error> { match *self { - Tag::End => {}, + Tag::End => {} Tag::Byte(val) => try!(buf.write_i8(val)), Tag::Short(val) => try!(buf.write_i16::(val)), Tag::Int(val) => try!(buf.write_i32::(val)), @@ -239,20 +240,20 @@ impl Serializable for Tag { Tag::ByteArray(ref val) => { try!((val.len() as i32).write_to(buf)); try!(buf.write_all(val)); - }, + } Tag::String(ref val) => try!(write_string(buf, val)), Tag::List(ref val) => { - if val.is_empty() { - try!(buf.write_u8(0)); - try!(buf.write_i32::(0)); - } else { - try!(buf.write_u8(val[0].internal_id())); - try!(buf.write_i32::(val.len() as i32)); - for e in val { - try!(e.write_to(buf)); - } + if val.is_empty() { + try!(buf.write_u8(0)); + try!(buf.write_i32::(0)); + } else { + try!(buf.write_u8(val[0].internal_id())); + try!(buf.write_i32::(val.len() as i32)); + for e in val { + try!(e.write_to(buf)); } - }, + } + } Tag::Compound(ref val) => { for (k, v) in val { try!(v.internal_id().write_to(buf)); @@ -260,19 +261,19 @@ impl Serializable for Tag { try!(v.write_to(buf)); } try!(buf.write_u8(0)); - }, + } Tag::IntArray(ref val) => { try!((val.len() as i32).write_to(buf)); for v in val { try!(v.write_to(buf)); } - }, + } } Result::Ok(()) } } -pub fn write_string(buf: &mut io::Write, s: &String)-> io::Result<()> { +pub fn write_string(buf: &mut io::Write, s: &String) -> io::Result<()> { let data = s.as_bytes(); try!((data.len() as i16).write_to(buf)); buf.write_all(data) diff --git a/protocol/src/types/bit/map.rs b/protocol/src/types/bit/map.rs index b1b9e05..4814f2a 100644 --- a/protocol/src/types/bit/map.rs +++ b/protocol/src/types/bit/map.rs @@ -15,14 +15,14 @@ pub struct Map { bits: Vec, bit_size: usize, - length: usize + length: usize, } #[test] fn test_map() { let mut map = Map::new(4096, 4); - for i in 0 .. 4096 { - for j in 0 .. 16 { + for i in 0..4096 { + for j in 0..16 { map.set(i, j); if map.get(i) != j { panic!("Fail"); @@ -33,11 +33,11 @@ fn test_map() { #[test] fn test_map_odd() { - for size in 1 .. 16 { - let mut map = Map::new(64*3, size); + for size in 1..16 { + let mut map = Map::new(64 * 3, size); let max = (1 << size) - 1; - for i in 0 .. 64*3 { - for j in 0 .. max { + for i in 0..64 * 3 { + for j in 0..max { map.set(i, j); if map.get(i) != j { panic!("Index: {} wanted {} and got {}", i, j, map.get(i)); @@ -52,9 +52,9 @@ impl Map { let mut map = Map { bit_size: size, length: len, - bits: Vec::with_capacity((len*size)/64) + bits: Vec::with_capacity((len * size) / 64), }; - for _ in 0 .. len { + for _ in 0..len { map.bits.push(0) } map @@ -62,7 +62,7 @@ impl Map { pub fn resize(self, size: usize) -> Map { let mut n = Map::new(self.length, size); - for i in 0 .. self.length { + for i in 0..self.length { n.set(i, self.get(i)); } n @@ -73,7 +73,7 @@ impl Map { let pos = i / 64; let mask = (1 << self.bit_size) - 1; let ii = i % 64; - self.bits[pos] = (self.bits[pos] & !(mask << ii )) | ((val << ii) as u64); + self.bits[pos] = (self.bits[pos] & !(mask << ii)) | ((val << ii) as u64); let pos2 = (i + self.bit_size - 1) / 64; if pos2 != pos { let used = 64 - ii; diff --git a/protocol/src/types/bit/set.rs b/protocol/src/types/bit/set.rs index e74f6c5..123b0f9 100644 --- a/protocol/src/types/bit/set.rs +++ b/protocol/src/types/bit/set.rs @@ -13,19 +13,19 @@ // limitations under the License. pub struct Set { - data : Vec + data: Vec, } #[test] fn test_set() { let mut set = Set::new(200); - for i in 0 .. 200 { + for i in 0..200 { if i % 3 == 0 { set.set(i, true) } } - for i in 0 .. 200 { - if set.get(i) != (i%3 == 0) { + for i in 0..200 { + if set.get(i) != (i % 3 == 0) { panic!("Fail") } } @@ -33,10 +33,8 @@ fn test_set() { impl Set { pub fn new(size: usize) -> Set { - let mut set = Set { - data: Vec::with_capacity(size) - }; - for _ in 0 .. size { + let mut set = Set { data: Vec::with_capacity(size) }; + for _ in 0..size { set.data.push(0) } set @@ -44,13 +42,13 @@ impl Set { pub fn set(&mut self, i: usize, v: bool) { if v { - self.data[i>>6] |= 1 << (i & 0x3F) + self.data[i >> 6] |= 1 << (i & 0x3F) } else { - self.data[i>>6] &= !(1 << (i & 0x3F)) + self.data[i >> 6] &= !(1 << (i & 0x3F)) } } pub fn get(&mut self, i: usize) -> bool { - (self.data[i>>6] & (1 << (i & 0x3F))) != 0 + (self.data[i >> 6] & (1 << (i & 0x3F))) != 0 } } diff --git a/protocol/src/types/blockpos.rs b/protocol/src/types/blockpos.rs index cc38604..8455811 100644 --- a/protocol/src/types/blockpos.rs +++ b/protocol/src/types/blockpos.rs @@ -15,7 +15,7 @@ extern crate byteorder; use std::fmt; -use protocol::{Serializable}; +use protocol::Serializable; use std::io; use std::io::{Read, Write}; use self::byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; @@ -26,11 +26,8 @@ pub struct Position(u64); impl Position { #[allow(dead_code)] fn new(x: i32, y: i32, z: i32) -> Position { - Position( - (((x as u64) & 0x3FFFFFF) << 38) | - (((y as u64) & 0xFFF) << 26) | - ((z as u64) & 0x3FFFFFF) - ) + Position((((x as u64) & 0x3FFFFFF) << 38) | (((y as u64) & 0xFFF) << 26) | + ((z as u64) & 0x3FFFFFF)) } fn get_x(&self) -> i32 { diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index f4281b6..b7443f3 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -18,7 +18,7 @@ use std::io; use std::io::{Read, Write}; use std::fmt; use protocol; -use protocol::{Serializable}; +use protocol::Serializable; use format; use item; @@ -30,7 +30,7 @@ pub struct MetadataKey { impl MetadataKey { #[allow(dead_code)] // TODO: Make const later when possible - /*const*/ fn new(index: i32) -> MetadataKey { + /*const*/ fn new(index: i32) -> MetadataKey { MetadataKey { index: index, ty: PhantomData, @@ -78,11 +78,10 @@ impl Serializable for Metadata { 4 => m.put_raw(index, try!(format::Component::read_from(buf))), 5 => m.put_raw(index, try!(Option::::read_from(buf))), 6 => m.put_raw(index, try!(bool::read_from(buf))), - 7 => m.put_raw(index, [ - try!(f32::read_from(buf)), - try!(f32::read_from(buf)), - try!(f32::read_from(buf)) - ]), + 7 => m.put_raw(index, + [try!(f32::read_from(buf)), + try!(f32::read_from(buf)), + try!(f32::read_from(buf))]), 8 => m.put_raw(index, try!(super::Position::read_from(buf))), 9 => { if try!(bool::read_from(buf)) { @@ -90,7 +89,7 @@ impl Serializable for Metadata { } else { m.put_raw::>(index, None); } - }, + } 10 => m.put_raw(index, try!(protocol::VarInt::read_from(buf))), 11 => { if try!(bool::read_from(buf)) { @@ -98,9 +97,11 @@ impl Serializable for Metadata { } else { m.put_raw::>(index, None); } - }, + } 12 => m.put_raw(index, try!(protocol::VarInt::read_from(buf)).0 as u16), - _ => return Err(io::Error::new(io::ErrorKind::InvalidInput, protocol::Error::Err("unknown metadata type".to_owned()))), + _ => return Err(io::Error::new(io::ErrorKind::InvalidInput, + protocol::Error::Err("unknown metadata type" + .to_owned()))), } } Ok(m) @@ -113,46 +114,46 @@ impl Serializable for Metadata { Value::Byte(ref val) => { try!(u8::write_to(&0, buf)); try!(val.write_to(buf)); - }, + } Value::Int(ref val) => { try!(u8::write_to(&1, buf)); try!(protocol::VarInt(*val).write_to(buf)); - }, + } Value::Float(ref val) => { try!(u8::write_to(&2, buf)); try!(val.write_to(buf)); - }, + } Value::String(ref val) => { try!(u8::write_to(&3, buf)); try!(val.write_to(buf)); - }, + } Value::FormatComponent(ref val) => { try!(u8::write_to(&4, buf)); try!(val.write_to(buf)); - }, + } Value::OptionalItemStack(ref val) => { try!(u8::write_to(&5, buf)); try!(val.write_to(buf)); - }, + } Value::Bool(ref val) => { try!(u8::write_to(&6, buf)); try!(val.write_to(buf)); - }, + } Value::Vector(ref val) => { try!(u8::write_to(&7, buf)); try!(val[0].write_to(buf)); try!(val[1].write_to(buf)); try!(val[2].write_to(buf)); - }, + } Value::Position(ref val) => { try!(u8::write_to(&8, buf)); try!(val.write_to(buf)); - }, + } Value::OptionalPosition(ref val) => { try!(u8::write_to(&9, buf)); try!(val.is_some().write_to(buf)); try!(val.write_to(buf)); - }, + } Value::Direction(ref val) => { try!(u8::write_to(&10, buf)); try!(val.write_to(buf)); @@ -161,7 +162,7 @@ impl Serializable for Metadata { try!(u8::write_to(&11, buf)); try!(val.is_some().write_to(buf)); try!(val.write_to(buf)); - }, + } Value::Block(ref val) => { try!(u8::write_to(&11, buf)); try!(protocol::VarInt(*val as i32).write_to(buf)); @@ -374,9 +375,9 @@ mod test { const TEST: MetadataKey = MetadataKey { - index: 0, - ty: PhantomData, - }; + index: 0, + ty: PhantomData, + }; #[test] fn basic() { diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index 034015f..ca88128 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -18,4 +18,4 @@ pub use self::blockpos::*; mod metadata; pub use self::metadata::*; -pub mod bit; \ No newline at end of file +pub mod bit; From 75654bbc661ee5742e8dc32a10b4b16486899017 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Wed, 16 Mar 2016 18:01:33 +0000 Subject: [PATCH 12/47] Clean up --- protocol/src/item.rs | 1 - protocol/src/types/metadata.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/protocol/src/item.rs b/protocol/src/item.rs index a6ab829..a26e57d 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -15,7 +15,6 @@ use nbt; use protocol::Serializable; use std::io; -use std::io::{Read, Write}; use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; #[derive(Debug)] diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index b7443f3..1fbd49f 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -15,7 +15,7 @@ use std::collections::HashMap; use std::marker::PhantomData; use std::io; -use std::io::{Read, Write}; +use std::io::Write; use std::fmt; use protocol; use protocol::Serializable; @@ -191,7 +191,7 @@ impl Default for Metadata { } #[derive(Debug)] -enum Value { +pub enum Value { Byte(i8), Int(i32), Float(f32), From 30c7dbeaea910ba8d5e2994826d243b55c5aad70 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Wed, 16 Mar 2016 18:25:35 +0000 Subject: [PATCH 13/47] Update copyright --- protocol/src/format.rs | 2 +- protocol/src/item.rs | 2 +- protocol/src/nbt/mod.rs | 2 +- protocol/src/types/bit/map.rs | 2 +- protocol/src/types/bit/mod.rs | 2 +- protocol/src/types/bit/set.rs | 2 +- protocol/src/types/blockpos.rs | 2 +- protocol/src/types/metadata.rs | 2 +- protocol/src/types/mod.rs | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 49c12ba..ba73f77 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -1,4 +1,4 @@ -// Copyright 2015 Matthew Collins +// Copyright 2016 Matthew Collins // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/protocol/src/item.rs b/protocol/src/item.rs index a26e57d..eeeeee3 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -1,4 +1,4 @@ -// Copyright 2015 Matthew Collins +// Copyright 2016 Matthew Collins // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index 32d4a64..45be019 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2015 Matthew Collins +// Copyright 2016 Matthew Collins // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/protocol/src/types/bit/map.rs b/protocol/src/types/bit/map.rs index 4814f2a..15136a9 100644 --- a/protocol/src/types/bit/map.rs +++ b/protocol/src/types/bit/map.rs @@ -1,4 +1,4 @@ -// Copyright 2015 Matthew Collins +// Copyright 2016 Matthew Collins // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/protocol/src/types/bit/mod.rs b/protocol/src/types/bit/mod.rs index bc345c6..6754eab 100644 --- a/protocol/src/types/bit/mod.rs +++ b/protocol/src/types/bit/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2015 Matthew Collins +// Copyright 2016 Matthew Collins // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/protocol/src/types/bit/set.rs b/protocol/src/types/bit/set.rs index 123b0f9..a650570 100644 --- a/protocol/src/types/bit/set.rs +++ b/protocol/src/types/bit/set.rs @@ -1,4 +1,4 @@ -// Copyright 2015 Matthew Collins +// Copyright 2016 Matthew Collins // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/protocol/src/types/blockpos.rs b/protocol/src/types/blockpos.rs index 8455811..9b56b72 100644 --- a/protocol/src/types/blockpos.rs +++ b/protocol/src/types/blockpos.rs @@ -1,4 +1,4 @@ -// Copyright 2015 Matthew Collins +// Copyright 2016 Matthew Collins // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 1fbd49f..78bb7eb 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -1,4 +1,4 @@ -// Copyright 2015 Matthew Collins +// Copyright 2016 Matthew Collins // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index ca88128..11e4d7c 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2015 Matthew Collins +// Copyright 2016 Matthew Collins // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From 469afb228b83877b6c0823ac25cb03e55af5de6c Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Thu, 17 Mar 2016 22:18:25 +0000 Subject: [PATCH 14/47] Implementation of components for the entity component system --- protocol/src/types/bit/set.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/protocol/src/types/bit/set.rs b/protocol/src/types/bit/set.rs index a650570..23ef4e8 100644 --- a/protocol/src/types/bit/set.rs +++ b/protocol/src/types/bit/set.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[derive(Clone)] pub struct Set { data: Vec, } @@ -33,11 +34,11 @@ fn test_set() { impl Set { pub fn new(size: usize) -> Set { - let mut set = Set { data: Vec::with_capacity(size) }; - for _ in 0..size { - set.data.push(0) - } - set + Set { data: vec![0; (size + 63) / 64] } + } + + pub fn resize(&mut self, new_size: usize) { + self.data.resize((new_size + 63) / 64, 0); } pub fn set(&mut self, i: usize, v: bool) { @@ -48,7 +49,17 @@ impl Set { } } - pub fn get(&mut self, i: usize) -> bool { + pub fn get(&self, i: usize) -> bool { (self.data[i >> 6] & (1 << (i & 0x3F))) != 0 } + + pub fn includes_set(&self, other: &Set) -> bool { + debug_assert!(self.data.len() == other.data.len()); + for (a, b) in self.data.iter().zip(&other.data) { + if a & b != *b { + return false; + } + } + true + } } From eaea15e4a146b777a47d39fa708ce7b9b18e64d4 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Fri, 18 Mar 2016 10:25:09 +0000 Subject: [PATCH 15/47] Allow searching for entities within the manager --- protocol/src/types/bit/set.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/protocol/src/types/bit/set.rs b/protocol/src/types/bit/set.rs index 23ef4e8..0a620ad 100644 --- a/protocol/src/types/bit/set.rs +++ b/protocol/src/types/bit/set.rs @@ -41,6 +41,10 @@ impl Set { self.data.resize((new_size + 63) / 64, 0); } + pub fn capacity(&self) -> usize { + self.data.len() * 64 + } + pub fn set(&mut self, i: usize, v: bool) { if v { self.data[i >> 6] |= 1 << (i & 0x3F) @@ -54,7 +58,6 @@ impl Set { } pub fn includes_set(&self, other: &Set) -> bool { - debug_assert!(self.data.len() == other.data.len()); for (a, b) in self.data.iter().zip(&other.data) { if a & b != *b { return false; From ddf3a7981cfed5f660c77ab25d01d8577827c4f0 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Fri, 18 Mar 2016 22:24:30 +0000 Subject: [PATCH 16/47] Base implementation for worlds/blocks --- protocol/src/macros.rs | 25 +++++++++++++++++++ protocol/src/types/bit/map.rs | 4 ++-- protocol/src/types/mod.rs | 1 + protocol/src/types/nibble.rs | 45 +++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 protocol/src/macros.rs create mode 100644 protocol/src/types/nibble.rs diff --git a/protocol/src/macros.rs b/protocol/src/macros.rs new file mode 100644 index 0000000..bf2b7a2 --- /dev/null +++ b/protocol/src/macros.rs @@ -0,0 +1,25 @@ + + +#[doc(hidden)] +#[macro_export] +macro_rules! create_ids { + ($t:ty, ) => (); + ($t:ty, prev($prev:ident), $name:ident) => ( + #[allow(non_upper_case_globals)] + pub const $name: $t = $prev + 1; + ); + ($t:ty, prev($prev:ident), $name:ident, $($n:ident),+) => ( + #[allow(non_upper_case_globals)] + pub const $name: $t = $prev + 1; + create_ids!($t, prev($name), $($n),+); + ); + ($t:ty, $name:ident, $($n:ident),+) => ( + #[allow(non_upper_case_globals)] + pub const $name: $t = 0; + create_ids!($t, prev($name), $($n),+); + ); + ($t:ty, $name:ident) => ( + #[allow(non_upper_case_globals)] + pub const $name: $t = 0; + ); +} diff --git a/protocol/src/types/bit/map.rs b/protocol/src/types/bit/map.rs index 15136a9..a847bb3 100644 --- a/protocol/src/types/bit/map.rs +++ b/protocol/src/types/bit/map.rs @@ -14,7 +14,7 @@ pub struct Map { bits: Vec, - bit_size: usize, + pub bit_size: usize, length: usize, } @@ -60,7 +60,7 @@ impl Map { map } - pub fn resize(self, size: usize) -> Map { + pub fn resize(&self, size: usize) -> Map { let mut n = Map::new(self.length, size); for i in 0..self.length { n.set(i, self.get(i)); diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index 11e4d7c..682180e 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -19,3 +19,4 @@ mod metadata; pub use self::metadata::*; pub mod bit; +pub mod nibble; diff --git a/protocol/src/types/nibble.rs b/protocol/src/types/nibble.rs new file mode 100644 index 0000000..1b62d2e --- /dev/null +++ b/protocol/src/types/nibble.rs @@ -0,0 +1,45 @@ +// Copyright 2015 Matthew Collins +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +pub struct Array { + data: Vec, +} + +impl Array { + pub fn new(size: usize) -> Array { + Array { + data: vec![0; (size + 1) >> 1], + } + } + + pub fn get(&self, idx: usize) -> u8 { + let val = self.data[idx>>1]; + if idx&1 == 0 { + val & 0xF + } else { + val >> 4 + } + } + + pub fn set(&mut self, idx: usize, val: u8) { + let i = idx >> 1; + let old = self.data[i]; + if idx&1 == 0 { + self.data[i] = (old & 0xF0) | (val & 0xF); + } else { + self.data[i] = (old & 0x0F) | ((val & 0xF) << 4); + } + } +} From a42c1e412ae141ec897ef50d7faf7b2c6d5f025c Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Mon, 21 Mar 2016 14:05:13 +0000 Subject: [PATCH 17/47] Implement chunk loading --- protocol/src/types/bit/map.rs | 7 +++++++ protocol/src/types/nibble.rs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/protocol/src/types/bit/map.rs b/protocol/src/types/bit/map.rs index a847bb3..ece65fd 100644 --- a/protocol/src/types/bit/map.rs +++ b/protocol/src/types/bit/map.rs @@ -59,6 +59,13 @@ impl Map { } map } + pub fn from_raw(bits: Vec, size: usize) -> Map { + Map { + length: (bits.len()*64 + 63) / size, + bit_size: size, + bits: bits, + } + } pub fn resize(&self, size: usize) -> Map { let mut n = Map::new(self.length, size); diff --git a/protocol/src/types/nibble.rs b/protocol/src/types/nibble.rs index 1b62d2e..91ecdc8 100644 --- a/protocol/src/types/nibble.rs +++ b/protocol/src/types/nibble.rs @@ -14,7 +14,7 @@ pub struct Array { - data: Vec, + pub data: Vec, } impl Array { From ce6f5c963cb587469966d9502364310e68e2b3be Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Thu, 24 Mar 2016 15:39:57 +0000 Subject: [PATCH 18/47] Initial block model support --- protocol/src/types/blockpos.rs | 2 +- protocol/src/types/hash.rs | 24 ++++++++++++++++++++++++ protocol/src/types/mod.rs | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 protocol/src/types/hash.rs diff --git a/protocol/src/types/blockpos.rs b/protocol/src/types/blockpos.rs index 9b56b72..03d791c 100644 --- a/protocol/src/types/blockpos.rs +++ b/protocol/src/types/blockpos.rs @@ -17,7 +17,7 @@ extern crate byteorder; use std::fmt; use protocol::Serializable; use std::io; -use std::io::{Read, Write}; +use std::io::Write; use self::byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; #[derive(Clone, Copy)] diff --git a/protocol/src/types/hash.rs b/protocol/src/types/hash.rs new file mode 100644 index 0000000..cf16af9 --- /dev/null +++ b/protocol/src/types/hash.rs @@ -0,0 +1,24 @@ + + +use std::hash::Hasher; + +pub struct FNVHash(u64); + +impl Hasher for FNVHash { + fn write(&mut self, bytes: &[u8]) { + for b in bytes { + self.0 = self.0.wrapping_mul(0x100000001b3); + self.0 ^= *b as u64 + } + } + + fn finish(&self) -> u64 { + self.0 + } +} + +impl Default for FNVHash { + fn default() -> Self { + FNVHash(0xcbf29ce484222325) + } +} diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index 682180e..5d270fd 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -20,3 +20,4 @@ pub use self::metadata::*; pub mod bit; pub mod nibble; +pub mod hash; From 780676ec65f1d45b347fe294e4896042f37d1479 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Fri, 25 Mar 2016 20:56:45 +0000 Subject: [PATCH 19/47] Update to 1.9.0 --- protocol/src/types/metadata.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 78bb7eb..6933d59 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -29,8 +29,7 @@ pub struct MetadataKey { impl MetadataKey { #[allow(dead_code)] - // TODO: Make const later when possible - /*const*/ fn new(index: i32) -> MetadataKey { + const fn new(index: i32) -> MetadataKey { MetadataKey { index: index, ty: PhantomData, From 9a69cd1fa7d48cedaea64bb1ffe8df2e7c6e4487 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Sat, 26 Mar 2016 11:46:37 +0000 Subject: [PATCH 20/47] Move Direction and BlockVertex into better locations --- protocol/src/types/mod.rs | 95 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index 5d270fd..b858aeb 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -21,3 +21,98 @@ pub use self::metadata::*; pub mod bit; pub mod nibble; pub mod hash; + +use model::{PRECOMPUTED_VERTS, BlockVertex}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Direction { + Invalid, + Up, + Down, + North, + South, + West, + East, +} + +impl Direction { + pub fn all() -> Vec { + vec![ + Direction::Up, Direction::Down, + Direction::North, Direction::South, + Direction::West, Direction::East, + ] + } + + pub fn from_string(val: &str) -> Direction { + match val { + "up" => Direction::Up, + "down" => Direction::Down, + "north" => Direction::North, + "south" => Direction::South, + "west" => Direction::West, + "east" => Direction::East, + _ => Direction::Invalid, + } + } + + pub fn opposite(&self) -> Direction { + match *self { + Direction::Up => Direction::Down, + Direction::Down => Direction::Up, + Direction::North => Direction::South, + Direction::South => Direction::North, + Direction::West => Direction::East, + Direction::East => Direction::West, + _ => unreachable!(), + } + } + + pub fn get_verts(&self) -> &'static [BlockVertex; 4] { + match *self { + Direction::Up => PRECOMPUTED_VERTS[0], + Direction::Down => PRECOMPUTED_VERTS[1], + Direction::North => PRECOMPUTED_VERTS[2], + Direction::South => PRECOMPUTED_VERTS[3], + Direction::West => PRECOMPUTED_VERTS[4], + Direction::East => PRECOMPUTED_VERTS[5], + _ => unreachable!(), + } + } + + pub fn get_offset(&self) -> (i32, i32, i32) { + match *self { + Direction::Up => (0, 1, 0), + Direction::Down => (0, -1, 0), + Direction::North => (0, 0, -1), + Direction::South => (0, 0, 1), + Direction::West => (-1, 0, 0), + Direction::East => (1, 0, 0), + _ => unreachable!(), + } + } + + pub fn as_string(&self) -> &'static str { + match *self { + Direction::Up => "up", + Direction::Down => "down", + Direction::North => "north", + Direction::South => "south", + Direction::West => "west", + Direction::East => "east", + Direction::Invalid => "invalid", + } + } + + pub fn index(&self) -> usize { + match *self { + Direction::Up => 0, + Direction::Down => 1, + Direction::North => 2, + Direction::South => 3, + Direction::West => 4, + Direction::East => 5, + _ => unreachable!(), + } + } +} From f6ac1123a2dee50398140317adad9e8c4827305d Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Sat, 26 Mar 2016 13:08:01 +0000 Subject: [PATCH 21/47] Implement stairs --- protocol/src/types/mod.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index b858aeb..330263c 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -24,7 +24,7 @@ pub mod hash; use model::{PRECOMPUTED_VERTS, BlockVertex}; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Direction { Invalid, Up, @@ -68,6 +68,30 @@ impl Direction { } } + pub fn clockwise(&self) -> Direction { + match *self { + Direction::Up => Direction::Up, + Direction::Down => Direction::Down, + Direction::East => Direction::South, + Direction::West => Direction::North, + Direction::South => Direction::West, + Direction::North => Direction::East, + _ => unreachable!(), + } + } + + pub fn counter_clockwise(&self) -> Direction { + match *self { + Direction::Up => Direction::Up, + Direction::Down => Direction::Down, + Direction::East => Direction::North, + Direction::West => Direction::South, + Direction::South => Direction::East, + Direction::North => Direction::West, + _ => unreachable!(), + } + } + pub fn get_verts(&self) -> &'static [BlockVertex; 4] { match *self { Direction::Up => PRECOMPUTED_VERTS[0], From 2589b169ca547e58dfd16fa3bbc7e48c686212d5 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Sat, 26 Mar 2016 14:24:26 +0000 Subject: [PATCH 22/47] Follow some of clippy's suggestions --- protocol/src/format.rs | 7 +++---- protocol/src/nbt/mod.rs | 2 +- protocol/src/types/bit/map.rs | 6 +++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index ba73f77..6b4ba38 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -171,8 +171,8 @@ impl fmt::Display for Color { } impl Color { - fn from_string(val: &String) -> Self { - match val.as_ref() { + fn from_string(val: &str) -> Self { + match val { "black" => Color::Black, "dark_blue" => Color::DarkBlue, "dark_green" => Color::DarkGreen, @@ -188,7 +188,6 @@ impl Color { "red" => Color::Red, "light_purple" => Color::LightPurple, "yellow" => Color::Yellow, - "white" => Color::White, val if val.len() == 7 && val.as_bytes()[0] == b'#' => { let r = match u8::from_str_radix(&val[1..3], 16) { Ok(r) => r, @@ -204,7 +203,7 @@ impl Color { }; Color::RGB(r, g, b) } - _ => Color::White, + "white" | _ => Color::White, } } diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index 45be019..4ea53bf 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -273,7 +273,7 @@ impl Serializable for Tag { } } -pub fn write_string(buf: &mut io::Write, s: &String) -> io::Result<()> { +pub fn write_string(buf: &mut io::Write, s: &str) -> io::Result<()> { let data = s.as_bytes(); try!((data.len() as i16).write_to(buf)); buf.write_all(data) diff --git a/protocol/src/types/bit/map.rs b/protocol/src/types/bit/map.rs index ece65fd..a281cdd 100644 --- a/protocol/src/types/bit/map.rs +++ b/protocol/src/types/bit/map.rs @@ -95,11 +95,11 @@ impl Map { let mask = (1 << self.bit_size) - 1; let ii = i % 64; let pos2 = (i + self.bit_size - 1) / 64; - if pos2 != pos { + if pos2 == pos { + ((self.bits[pos] >> ii) & mask) as usize + } else { let used = 64 - ii; (((self.bits[pos] >> ii) | (self.bits[pos2] << used)) & mask) as usize - } else { - ((self.bits[pos] >> ii) & mask) as usize } } } From 3f8bc10bb07e76988c8c1df8908d242e0d6c3e27 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Sat, 26 Mar 2016 22:21:47 +0000 Subject: [PATCH 23/47] Initial entity work, moved self handling to an entity --- protocol/src/types/mod.rs | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index 330263c..562cbd0 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -140,3 +140,45 @@ impl Direction { } } } + + + +#[derive(Clone, Copy, Debug)] +pub enum Gamemode { + Survival = 0, + Creative = 1, + Adventure = 2, + Spectator = 3, +} + +impl Gamemode { + pub fn from_int(val: i32) -> Gamemode { + match val { + 3 => Gamemode::Spectator, + 2 => Gamemode::Adventure, + 1 => Gamemode::Creative, + 0 | _ => Gamemode::Survival, + } + } + + pub fn can_fly(&self) -> bool { + match *self { + Gamemode::Creative | Gamemode::Spectator => true, + _ => false, + } + } + + pub fn always_fly(&self) -> bool { + match *self { + Gamemode::Spectator => true, + _ => false, + } + } + + pub fn noclip(&self) -> bool { + match *self { + Gamemode::Spectator => true, + _ => false, + } + } +} From 88c0f3da289d20857f8c81ffe1f7c37ff880d3f2 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Thu, 31 Mar 2016 15:26:07 +0100 Subject: [PATCH 24/47] Handle block updates from the server --- protocol/src/types/blockpos.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/protocol/src/types/blockpos.rs b/protocol/src/types/blockpos.rs index 03d791c..6623d2b 100644 --- a/protocol/src/types/blockpos.rs +++ b/protocol/src/types/blockpos.rs @@ -25,20 +25,20 @@ pub struct Position(u64); impl Position { #[allow(dead_code)] - fn new(x: i32, y: i32, z: i32) -> Position { + pub fn new(x: i32, y: i32, z: i32) -> Position { Position((((x as u64) & 0x3FFFFFF) << 38) | (((y as u64) & 0xFFF) << 26) | ((z as u64) & 0x3FFFFFF)) } - fn get_x(&self) -> i32 { + pub fn get_x(&self) -> i32 { ((self.0 as i64) >> 38) as i32 } - fn get_y(&self) -> i32 { + pub fn get_y(&self) -> i32 { (((self.0 as i64) >> 26) & 0xFFF) as i32 } - fn get_z(&self) -> i32 { + pub fn get_z(&self) -> i32 { ((self.0 as i64) << 38 >> 38) as i32 } } From df9db09004da3d97ed8d32cb4605a28329358f8f Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Sat, 2 Apr 2016 16:24:50 +0100 Subject: [PATCH 25/47] Fix a bit::Map overflow on 32 bit machines --- protocol/src/types/bit/map.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocol/src/types/bit/map.rs b/protocol/src/types/bit/map.rs index a281cdd..3695df8 100644 --- a/protocol/src/types/bit/map.rs +++ b/protocol/src/types/bit/map.rs @@ -78,9 +78,9 @@ impl Map { pub fn set(&mut self, i: usize, val: usize) { let i = i * self.bit_size; let pos = i / 64; - let mask = (1 << self.bit_size) - 1; + let mask = (1u64 << self.bit_size) - 1; let ii = i % 64; - self.bits[pos] = (self.bits[pos] & !(mask << ii)) | ((val << ii) as u64); + self.bits[pos] = (self.bits[pos] & !(mask << ii)) | ((val as u64) << ii); let pos2 = (i + self.bit_size - 1) / 64; if pos2 != pos { let used = 64 - ii; From da40508291c2790075c9d6986f3f3f907b49582a Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Sun, 3 Apr 2016 20:53:40 +0100 Subject: [PATCH 26/47] Replace usages of x,y,z for block positions with Position --- protocol/src/types/blockpos.rs | 66 ------------------ protocol/src/types/metadata.rs | 15 ++-- protocol/src/types/mod.rs | 124 --------------------------------- 3 files changed, 8 insertions(+), 197 deletions(-) delete mode 100644 protocol/src/types/blockpos.rs diff --git a/protocol/src/types/blockpos.rs b/protocol/src/types/blockpos.rs deleted file mode 100644 index 6623d2b..0000000 --- a/protocol/src/types/blockpos.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2016 Matthew Collins -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -extern crate byteorder; - -use std::fmt; -use protocol::Serializable; -use std::io; -use std::io::Write; -use self::byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; - -#[derive(Clone, Copy)] -pub struct Position(u64); - -impl Position { - #[allow(dead_code)] - pub fn new(x: i32, y: i32, z: i32) -> Position { - Position((((x as u64) & 0x3FFFFFF) << 38) | (((y as u64) & 0xFFF) << 26) | - ((z as u64) & 0x3FFFFFF)) - } - - pub fn get_x(&self) -> i32 { - ((self.0 as i64) >> 38) as i32 - } - - pub fn get_y(&self) -> i32 { - (((self.0 as i64) >> 26) & 0xFFF) as i32 - } - - pub fn get_z(&self) -> i32 { - ((self.0 as i64) << 38 >> 38) as i32 - } -} - -impl Default for Position { - fn default() -> Position { - Position(0) - } -} - -impl fmt::Debug for Position { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "<{},{},{}>", self.get_x(), self.get_y(), self.get_z()) - } -} - -impl Serializable for Position { - fn read_from(buf: &mut io::Read) -> Result { - Result::Ok(Position(try!(buf.read_u64::()))) - } - fn write_to(&self, buf: &mut io::Write) -> Result<(), io::Error> { - try!(buf.write_u64::(self.0)); - Result::Ok(()) - } -} diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 6933d59..eab44a6 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -21,6 +21,7 @@ use protocol; use protocol::Serializable; use format; use item; +use shared::Position; pub struct MetadataKey { index: i32, @@ -81,12 +82,12 @@ impl Serializable for Metadata { [try!(f32::read_from(buf)), try!(f32::read_from(buf)), try!(f32::read_from(buf))]), - 8 => m.put_raw(index, try!(super::Position::read_from(buf))), + 8 => m.put_raw(index, try!(Position::read_from(buf))), 9 => { if try!(bool::read_from(buf)) { - m.put_raw(index, try!(Option::::read_from(buf))); + m.put_raw(index, try!(Option::::read_from(buf))); } else { - m.put_raw::>(index, None); + m.put_raw::>(index, None); } } 10 => m.put_raw(index, try!(protocol::VarInt::read_from(buf))), @@ -199,8 +200,8 @@ pub enum Value { OptionalItemStack(Option), Bool(bool), Vector([f32; 3]), - Position(super::Position), - OptionalPosition(Option), + Position(Position), + OptionalPosition(Option), Direction(protocol::VarInt), // TODO: Proper type OptionalUUID(Option), Block(u16), // TODO: Proper type @@ -307,7 +308,7 @@ impl MetaValue for [f32; 3] { } } -impl MetaValue for super::Position { +impl MetaValue for Position { fn unwrap(value: &Value) -> &Self { match *value { Value::Position(ref val) => val, @@ -319,7 +320,7 @@ impl MetaValue for super::Position { } } -impl MetaValue for Option { +impl MetaValue for Option { fn unwrap(value: &Value) -> &Self { match *value { Value::OptionalPosition(ref val) => val, diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index 562cbd0..5232c8c 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod blockpos; -pub use self::blockpos::*; - mod metadata; pub use self::metadata::*; @@ -22,127 +19,6 @@ pub mod bit; pub mod nibble; pub mod hash; -use model::{PRECOMPUTED_VERTS, BlockVertex}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum Direction { - Invalid, - Up, - Down, - North, - South, - West, - East, -} - -impl Direction { - pub fn all() -> Vec { - vec![ - Direction::Up, Direction::Down, - Direction::North, Direction::South, - Direction::West, Direction::East, - ] - } - - pub fn from_string(val: &str) -> Direction { - match val { - "up" => Direction::Up, - "down" => Direction::Down, - "north" => Direction::North, - "south" => Direction::South, - "west" => Direction::West, - "east" => Direction::East, - _ => Direction::Invalid, - } - } - - pub fn opposite(&self) -> Direction { - match *self { - Direction::Up => Direction::Down, - Direction::Down => Direction::Up, - Direction::North => Direction::South, - Direction::South => Direction::North, - Direction::West => Direction::East, - Direction::East => Direction::West, - _ => unreachable!(), - } - } - - pub fn clockwise(&self) -> Direction { - match *self { - Direction::Up => Direction::Up, - Direction::Down => Direction::Down, - Direction::East => Direction::South, - Direction::West => Direction::North, - Direction::South => Direction::West, - Direction::North => Direction::East, - _ => unreachable!(), - } - } - - pub fn counter_clockwise(&self) -> Direction { - match *self { - Direction::Up => Direction::Up, - Direction::Down => Direction::Down, - Direction::East => Direction::North, - Direction::West => Direction::South, - Direction::South => Direction::East, - Direction::North => Direction::West, - _ => unreachable!(), - } - } - - pub fn get_verts(&self) -> &'static [BlockVertex; 4] { - match *self { - Direction::Up => PRECOMPUTED_VERTS[0], - Direction::Down => PRECOMPUTED_VERTS[1], - Direction::North => PRECOMPUTED_VERTS[2], - Direction::South => PRECOMPUTED_VERTS[3], - Direction::West => PRECOMPUTED_VERTS[4], - Direction::East => PRECOMPUTED_VERTS[5], - _ => unreachable!(), - } - } - - pub fn get_offset(&self) -> (i32, i32, i32) { - match *self { - Direction::Up => (0, 1, 0), - Direction::Down => (0, -1, 0), - Direction::North => (0, 0, -1), - Direction::South => (0, 0, 1), - Direction::West => (-1, 0, 0), - Direction::East => (1, 0, 0), - _ => unreachable!(), - } - } - - pub fn as_string(&self) -> &'static str { - match *self { - Direction::Up => "up", - Direction::Down => "down", - Direction::North => "north", - Direction::South => "south", - Direction::West => "west", - Direction::East => "east", - Direction::Invalid => "invalid", - } - } - - pub fn index(&self) -> usize { - match *self { - Direction::Up => 0, - Direction::Down => 1, - Direction::North => 2, - Direction::South => 3, - Direction::West => 4, - Direction::East => 5, - _ => unreachable!(), - } - } -} - - - #[derive(Clone, Copy, Debug)] pub enum Gamemode { Survival = 0, From 5f6e41f7007328d945eff33d9c722b5b4d1aed89 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Mon, 4 Apr 2016 12:37:21 +0100 Subject: [PATCH 27/47] Optimize chunk loading --- protocol/src/types/bit/map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/src/types/bit/map.rs b/protocol/src/types/bit/map.rs index 3695df8..11979fe 100644 --- a/protocol/src/types/bit/map.rs +++ b/protocol/src/types/bit/map.rs @@ -61,7 +61,7 @@ impl Map { } pub fn from_raw(bits: Vec, size: usize) -> Map { Map { - length: (bits.len()*64 + 63) / size, + length: (bits.len()*64 + (size-1)) / size, bit_size: size, bits: bits, } From d0704b2a674f36bd553a63f18c1b9034d886f070 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Mon, 4 Apr 2016 22:08:24 +0100 Subject: [PATCH 28/47] Block entity support, implement signs --- protocol/src/types/bit/set.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/protocol/src/types/bit/set.rs b/protocol/src/types/bit/set.rs index 0a620ad..8c9c221 100644 --- a/protocol/src/types/bit/set.rs +++ b/protocol/src/types/bit/set.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Set { data: Vec, } @@ -65,4 +65,10 @@ impl Set { } true } + + pub fn or(&mut self, other: &Set) { + for (a, b) in self.data.iter_mut().zip(&other.data) { + *a = (*a) | *b; + } + } } From 862cf9733139293875e6dc1c1dbd4812dadfc563 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Fri, 8 Apr 2016 18:46:07 +0100 Subject: [PATCH 29/47] Clean up the protocol implementation to use generics instead of trait objects --- protocol/src/item.rs | 6 +++--- protocol/src/nbt/mod.rs | 15 +++++++-------- protocol/src/types/metadata.rs | 8 +++----- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/protocol/src/item.rs b/protocol/src/item.rs index eeeeee3..45e4017 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -13,7 +13,7 @@ // limitations under the License. use nbt; -use protocol::Serializable; +use protocol::{self, Serializable}; use std::io; use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; @@ -38,7 +38,7 @@ impl Default for Stack { } impl Serializable for Option { - fn read_from(buf: &mut io::Read) -> Result, io::Error> { + fn read_from(buf: &mut R) -> Result, protocol::Error> { let id = try!(buf.read_i16::()); if id == -1 { return Ok(None); @@ -50,7 +50,7 @@ impl Serializable for Option { tag: try!(Serializable::read_from(buf)), })) } - fn write_to(&self, buf: &mut io::Write) -> Result<(), io::Error> { + fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { match *self { Some(ref val) => { try!(buf.write_i16::(val.id as i16)); diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index 4ea53bf..5883c9e 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -172,7 +172,7 @@ impl Tag { } } - fn read_type(id: u8, buf: &mut io::Read) -> Result { + fn read_type(id: u8, buf: &mut R) -> Result { match id { 0 => unreachable!(), 1 => Ok(Tag::Byte(try!(buf.read_i8()))), @@ -217,18 +217,17 @@ impl Tag { } data })), - _ => Err(io::Error::new(io::ErrorKind::InvalidData, - protocol::Error::Err("invalid tag".to_owned()))), + _ => Err(protocol::Error::Err("invalid tag".to_owned())), } } } impl Serializable for Tag { - fn read_from(buf: &mut io::Read) -> Result { + fn read_from(buf: &mut R) -> Result { Tag::read_type(10, buf) } - fn write_to(&self, buf: &mut io::Write) -> Result<(), io::Error> { + fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { match *self { Tag::End => {} Tag::Byte(val) => try!(buf.write_i8(val)), @@ -273,13 +272,13 @@ impl Serializable for Tag { } } -pub fn write_string(buf: &mut io::Write, s: &str) -> io::Result<()> { +pub fn write_string(buf: &mut W, s: &str) -> Result<(), protocol::Error> { let data = s.as_bytes(); try!((data.len() as i16).write_to(buf)); - buf.write_all(data) + buf.write_all(data).map_err(|v| v.into()) } -pub fn read_string(buf: &mut io::Read) -> io::Result { +pub fn read_string(buf: &mut R) -> Result { let len: i16 = try!(buf.read_i16::()); let mut ret = String::new(); try!(buf.take(len as u64).read_to_string(&mut ret)); diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index eab44a6..e5c8040 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -62,7 +62,7 @@ impl Metadata { impl Serializable for Metadata { - fn read_from(buf: &mut io::Read) -> Result { + fn read_from(buf: &mut R) -> Result { let mut m = Metadata::new(); loop { let index = try!(u8::read_from(buf)) as i32; @@ -99,15 +99,13 @@ impl Serializable for Metadata { } } 12 => m.put_raw(index, try!(protocol::VarInt::read_from(buf)).0 as u16), - _ => return Err(io::Error::new(io::ErrorKind::InvalidInput, - protocol::Error::Err("unknown metadata type" - .to_owned()))), + _ => return Err(protocol::Error::Err("unknown metadata type".to_owned())), } } Ok(m) } - fn write_to(&self, buf: &mut io::Write) -> Result<(), io::Error> { + fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { for (k, v) in &self.map { try!((*k as u8).write_to(buf)); match *v { From 49b1ae1dbc1de775983d5e8933fa5cb3735d8c6d Mon Sep 17 00:00:00 2001 From: Techcable Date: Sun, 10 Jul 2016 04:23:59 -0700 Subject: [PATCH 30/47] Update to minecraft 1.10.2 --- protocol/src/format.rs | 14 ++++++++++++++ protocol/src/nbt/mod.rs | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 6b4ba38..1b1bad9 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -22,6 +22,20 @@ pub enum Component { } impl Component { + + pub fn from_string(str: &str) -> Self { + let mut component; + match serde_json::from_str::(str) { + Ok(value) => component = Component::from_value(&value), + // Sometimes mojang sends a literal string, so we should interpret it literally + Err(_) => { + component = Component::Text(TextComponent::new(str)); + convert_legacy(&mut component); + }, + } + return component; + } + pub fn from_value(v: &serde_json::Value) -> Self { let mut modifier = Modifier::from_value(v); if let Some(val) = v.as_string() { diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index 5883c9e..ecd9495 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -20,7 +20,7 @@ use super::protocol::Serializable; use super::protocol; use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Tag { End, Byte(i8), @@ -36,7 +36,7 @@ pub enum Tag { IntArray(Vec), } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct NamedTag(pub String, pub Tag); impl Tag { From 0f41b0effee35599980c79d4d34b8b8dde185cca Mon Sep 17 00:00:00 2001 From: llogiq Date: Thu, 15 Sep 2016 16:15:52 +0200 Subject: [PATCH 31/47] Fixed another batch of clippy warnings Those are mostly readability-related. Also did a cargo update. --- protocol/src/format.rs | 2 +- protocol/src/nbt/mod.rs | 2 +- protocol/src/types/bit/set.rs | 2 +- protocol/src/types/metadata.rs | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 1b1bad9..e75f3ec 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -33,7 +33,7 @@ impl Component { convert_legacy(&mut component); }, } - return component; + component } pub fn from_value(v: &serde_json::Value) -> Self { diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index ecd9495..0ded16d 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -14,7 +14,7 @@ use std::collections::HashMap; use std::io; -use std::io::{Read, Write}; +use std::io::Read; use super::protocol::Serializable; use super::protocol; diff --git a/protocol/src/types/bit/set.rs b/protocol/src/types/bit/set.rs index 8c9c221..894d936 100644 --- a/protocol/src/types/bit/set.rs +++ b/protocol/src/types/bit/set.rs @@ -68,7 +68,7 @@ impl Set { pub fn or(&mut self, other: &Set) { for (a, b) in self.data.iter_mut().zip(&other.data) { - *a = (*a) | *b; + *a |= *b; } } } diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index e5c8040..0cf30be 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -15,7 +15,6 @@ use std::collections::HashMap; use std::marker::PhantomData; use std::io; -use std::io::Write; use std::fmt; use protocol; use protocol::Serializable; From 7e5bb999e4571497745f1c3c4d5011b423329f5e Mon Sep 17 00:00:00 2001 From: iceiix <43691553+iceiix@users.noreply.github.com> Date: Tue, 23 Oct 2018 18:47:21 -0700 Subject: [PATCH 32/47] Update to serde_json 1.0 (#6) * Replace find() with get() * Update for renamed as_string->as_str and as_boolean->as_bool https://github.com/serde-rs/json/releases/tag/v0.8.0 Value::as_string() has been renamed to as_str() and Value::as_boolean() has been renamed to as_bool() to improve consistency https://github.com/serde-rs/json/issues/126 * No serde_json::Value::I64/U64/F64 anymore, only Number * Update from lookup() to pointer(), using JSON pointer syntax https://github.com/iceiix/steven/pull/6#issuecomment-432472123 * Remove unused and removed ObjectBuilder import * Use into_iter().collect() to convert BTreeMap to serde_json::Map * Change parse_rules to accept serde_json::Map instead of BTreeMap * Remove unused serde_json macro_use * Update Cargo.lock --- protocol/src/format.rs | 22 +++++++++++----------- protocol/src/nbt/mod.rs | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index e75f3ec..9eb6ceb 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -38,12 +38,12 @@ impl Component { pub fn from_value(v: &serde_json::Value) -> Self { let mut modifier = Modifier::from_value(v); - if let Some(val) = v.as_string() { + if let Some(val) = v.as_str() { Component::Text(TextComponent { text: val.to_owned(), modifier: modifier, }) - } else if v.find("text").is_some() { + } else if v.get("text").is_some() { Component::Text(TextComponent::from_value(v, modifier)) } else { modifier.color = Some(Color::RGB(255, 0, 0)); @@ -92,17 +92,17 @@ pub struct Modifier { impl Modifier { pub fn from_value(v: &serde_json::Value) -> Self { let mut m = Modifier { - bold: v.find("bold").map_or(Option::None, |v| v.as_boolean()), - italic: v.find("italic").map_or(Option::None, |v| v.as_boolean()), - underlined: v.find("underlined").map_or(Option::None, |v| v.as_boolean()), - strikethrough: v.find("strikethrough").map_or(Option::None, |v| v.as_boolean()), - obfuscated: v.find("obfuscated").map_or(Option::None, |v| v.as_boolean()), - color: v.find("color") - .map_or(Option::None, |v| v.as_string()) + bold: v.get("bold").map_or(Option::None, |v| v.as_bool()), + italic: v.get("italic").map_or(Option::None, |v| v.as_bool()), + underlined: v.get("underlined").map_or(Option::None, |v| v.as_bool()), + strikethrough: v.get("strikethrough").map_or(Option::None, |v| v.as_bool()), + obfuscated: v.get("obfuscated").map_or(Option::None, |v| v.as_bool()), + color: v.get("color") + .map_or(Option::None, |v| v.as_str()) .map(|v| Color::from_string(&v.to_owned())), extra: Option::None, }; - if let Some(extra) = v.find("extra") { + if let Some(extra) = v.get("extra") { if let Some(data) = extra.as_array() { let mut ex = Vec::new(); for e in data { @@ -135,7 +135,7 @@ impl TextComponent { pub fn from_value(v: &serde_json::Value, modifier: Modifier) -> Self { TextComponent { - text: v.find("text").unwrap().as_string().unwrap_or("").to_owned(), + text: v.get("text").unwrap().as_str().unwrap_or("").to_owned(), modifier: modifier, } } diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index 0ded16d..db4d302 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -127,7 +127,7 @@ impl Tag { } } - pub fn as_string(&self) -> Option<&str> { + pub fn as_str(&self) -> Option<&str> { match *self { Tag::String(ref val) => Some(&val[..]), _ => None, From d95b99c175955b24d7181d7b409f38c15c9f5b06 Mon Sep 17 00:00:00 2001 From: iceiix <43691553+iceiix@users.noreply.github.com> Date: Fri, 2 Nov 2018 16:57:23 -0700 Subject: [PATCH 33/47] Support beta Rust release. Closes #8 (#11) * Remove seemingly unneeded const on MetadataKey new * Change biome temperature/moisture to integer, x100 to remove floating-point so can use within stable 'const fn' * Remove unstable const_fn feature, now using stable const fn: see https://www.reddit.com/r/rust/comments/9msqfn/const_fn_soon_on_stable_rust/ * Test on Rust beta (awaiting 1.31 release for stable) * Update readme for beta Rust support --- protocol/src/types/metadata.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 0cf30be..59ea64d 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -29,7 +29,7 @@ pub struct MetadataKey { impl MetadataKey { #[allow(dead_code)] - const fn new(index: i32) -> MetadataKey { + fn new(index: i32) -> MetadataKey { MetadataKey { index: index, ty: PhantomData, From d31a58b3eb4c4e855674582cd6b1f18a6cc789d3 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 4 Nov 2018 11:33:23 -0800 Subject: [PATCH 34/47] Remove anonymous trait parameters, name _ for Rust 2018 https://rust-lang-nursery.github.io/edition-guide/rust-2018/trait-system/no-anon-params.html --- protocol/src/types/metadata.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 59ea64d..7616266 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -205,7 +205,7 @@ pub enum Value { } pub trait MetaValue { - fn unwrap(&Value) -> &Self; + fn unwrap(_: &Value) -> &Self; fn wrap(self) -> Value; } From 099e10195b068c5788377f52e9b2408440b96834 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 4 Nov 2018 11:34:53 -0800 Subject: [PATCH 35/47] Update try!() to new ? syntax for Rust 2018 edition Not automatically updated, see https://users.rust-lang.org/t/why-does-cargo-fix-replace-try-with-r-try-instead-of/21972/3 There are other tools to replace it, btu this is what I used: find src -name '*.rs' -exec perl -MRegexp::Common -0777 -pe'$bp=$RE{balanced}{-parens=>"()"}; s/try\!($bp)/substr($1, 1, length($1) - 2) . "?"/ges' -i {} \; --- protocol/src/format.rs | 4 +- protocol/src/item.rs | 18 +++--- protocol/src/nbt/mod.rs | 80 ++++++++++++------------- protocol/src/types/metadata.rs | 106 ++++++++++++++++----------------- 4 files changed, 104 insertions(+), 104 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 9eb6ceb..88dba9c 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -147,10 +147,10 @@ impl TextComponent { impl fmt::Display for TextComponent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{}", self.text)); + write!(f, "{}", self.text)?; if let Some(ref extra) = self.modifier.extra { for c in extra { - try!(write!(f, "{}", c)); + write!(f, "{}", c)?; } } Result::Ok(()) diff --git a/protocol/src/item.rs b/protocol/src/item.rs index 45e4017..dfea1c6 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -39,26 +39,26 @@ impl Default for Stack { impl Serializable for Option { fn read_from(buf: &mut R) -> Result, protocol::Error> { - let id = try!(buf.read_i16::()); + let id = buf.read_i16::()?; if id == -1 { return Ok(None); } Ok(Some(Stack { id: id as isize, - count: try!(buf.read_u8()) as isize, - damage: try!(buf.read_i16::()) as isize, - tag: try!(Serializable::read_from(buf)), + count: buf.read_u8()? as isize, + damage: buf.read_i16::()? as isize, + tag: Serializable::read_from(buf)?, })) } fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { match *self { Some(ref val) => { - try!(buf.write_i16::(val.id as i16)); - try!(buf.write_u8(val.count as u8)); - try!(buf.write_i16::(val.damage as i16)); - try!(val.tag.write_to(buf)); + buf.write_i16::(val.id as i16)?; + buf.write_u8(val.count as u8)?; + buf.write_i16::(val.damage as i16)?; + val.tag.write_to(buf)?; } - None => try!(buf.write_i16::(-1)), + None => buf.write_i16::(-1)?, } Result::Ok(()) } diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index db4d302..3e79578 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -175,45 +175,45 @@ impl Tag { fn read_type(id: u8, buf: &mut R) -> Result { match id { 0 => unreachable!(), - 1 => Ok(Tag::Byte(try!(buf.read_i8()))), - 2 => Ok(Tag::Short(try!(buf.read_i16::()))), - 3 => Ok(Tag::Int(try!(buf.read_i32::()))), - 4 => Ok(Tag::Long(try!(buf.read_i64::()))), - 5 => Ok(Tag::Float(try!(buf.read_f32::()))), - 6 => Ok(Tag::Double(try!(buf.read_f64::()))), + 1 => Ok(Tag::Byte(buf.read_i8()?)), + 2 => Ok(Tag::Short(buf.read_i16::()?)), + 3 => Ok(Tag::Int(buf.read_i32::()?)), + 4 => Ok(Tag::Long(buf.read_i64::()?)), + 5 => Ok(Tag::Float(buf.read_f32::()?)), + 6 => Ok(Tag::Double(buf.read_f64::()?)), 7 => Ok(Tag::ByteArray({ - let len: i32 = try!(Serializable::read_from(buf)); + let len: i32 = Serializable::read_from(buf)?; let mut data = Vec::with_capacity(len as usize); - try!(buf.take(len as u64).read_to_end(&mut data)); + buf.take(len as u64).read_to_end(&mut data)?; data })), - 8 => Ok(Tag::String(try!(read_string(buf)))), + 8 => Ok(Tag::String(read_string(buf)?)), 9 => { let mut l = Vec::new(); - let ty = try!(buf.read_u8()); - let len: i32 = try!(Serializable::read_from(buf)); + let ty = buf.read_u8()?; + let len: i32 = Serializable::read_from(buf)?; for _ in 0..len { - l.push(try!(Tag::read_type(ty, buf))); + l.push(Tag::read_type(ty, buf)?); } Ok(Tag::List(l)) } 10 => { let mut c = Tag::new_compound(); loop { - let ty = try!(buf.read_u8()); + let ty = buf.read_u8()?; if ty == 0 { break; } - let name: String = try!(read_string(buf)); - c.put(&name[..], try!(Tag::read_type(ty, buf))); + let name: String = read_string(buf)?; + c.put(&name[..], Tag::read_type(ty, buf)?); } Ok(c) } 11 => Ok(Tag::IntArray({ - let len: i32 = try!(Serializable::read_from(buf)); + let len: i32 = Serializable::read_from(buf)?; let mut data = Vec::with_capacity(len as usize); for _ in 0..len { - data.push(try!(buf.read_i32::())); + data.push(buf.read_i32::()?); } data })), @@ -230,41 +230,41 @@ impl Serializable for Tag { fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { match *self { Tag::End => {} - Tag::Byte(val) => try!(buf.write_i8(val)), - Tag::Short(val) => try!(buf.write_i16::(val)), - Tag::Int(val) => try!(buf.write_i32::(val)), - Tag::Long(val) => try!(buf.write_i64::(val)), - Tag::Float(val) => try!(buf.write_f32::(val)), - Tag::Double(val) => try!(buf.write_f64::(val)), + Tag::Byte(val) => buf.write_i8(val)?, + Tag::Short(val) => buf.write_i16::(val)?, + Tag::Int(val) => buf.write_i32::(val)?, + Tag::Long(val) => buf.write_i64::(val)?, + Tag::Float(val) => buf.write_f32::(val)?, + Tag::Double(val) => buf.write_f64::(val)?, Tag::ByteArray(ref val) => { - try!((val.len() as i32).write_to(buf)); - try!(buf.write_all(val)); + (val.len() as i32).write_to(buf)?; + buf.write_all(val)?; } - Tag::String(ref val) => try!(write_string(buf, val)), + Tag::String(ref val) => write_string(buf, val)?, Tag::List(ref val) => { if val.is_empty() { - try!(buf.write_u8(0)); - try!(buf.write_i32::(0)); + buf.write_u8(0)?; + buf.write_i32::(0)?; } else { - try!(buf.write_u8(val[0].internal_id())); - try!(buf.write_i32::(val.len() as i32)); + buf.write_u8(val[0].internal_id())?; + buf.write_i32::(val.len() as i32)?; for e in val { - try!(e.write_to(buf)); + e.write_to(buf)?; } } } Tag::Compound(ref val) => { for (k, v) in val { - try!(v.internal_id().write_to(buf)); - try!(write_string(buf, k)); - try!(v.write_to(buf)); + v.internal_id().write_to(buf)?; + write_string(buf, k)?; + v.write_to(buf)?; } - try!(buf.write_u8(0)); + buf.write_u8(0)?; } Tag::IntArray(ref val) => { - try!((val.len() as i32).write_to(buf)); + (val.len() as i32).write_to(buf)?; for v in val { - try!(v.write_to(buf)); + v.write_to(buf)?; } } } @@ -274,13 +274,13 @@ impl Serializable for Tag { pub fn write_string(buf: &mut W, s: &str) -> Result<(), protocol::Error> { let data = s.as_bytes(); - try!((data.len() as i16).write_to(buf)); + (data.len() as i16).write_to(buf)?; buf.write_all(data).map_err(|v| v.into()) } pub fn read_string(buf: &mut R) -> Result { - let len: i16 = try!(buf.read_i16::()); + let len: i16 = buf.read_i16::()?; let mut ret = String::new(); - try!(buf.take(len as u64).read_to_string(&mut ret)); + buf.take(len as u64).read_to_string(&mut ret)?; Result::Ok(ret) } diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 7616266..d59ba51 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -64,40 +64,40 @@ impl Serializable for Metadata { fn read_from(buf: &mut R) -> Result { let mut m = Metadata::new(); loop { - let index = try!(u8::read_from(buf)) as i32; + let index = u8::read_from(buf)? as i32; if index == 0xFF { break; } - let ty = try!(u8::read_from(buf)); + let ty = u8::read_from(buf)?; match ty { - 0 => m.put_raw(index, try!(i8::read_from(buf))), - 1 => m.put_raw(index, try!(protocol::VarInt::read_from(buf)).0), - 2 => m.put_raw(index, try!(f32::read_from(buf))), - 3 => m.put_raw(index, try!(String::read_from(buf))), - 4 => m.put_raw(index, try!(format::Component::read_from(buf))), - 5 => m.put_raw(index, try!(Option::::read_from(buf))), - 6 => m.put_raw(index, try!(bool::read_from(buf))), + 0 => m.put_raw(index, i8::read_from(buf)?), + 1 => m.put_raw(index, protocol::VarInt::read_from(buf)?.0), + 2 => m.put_raw(index, f32::read_from(buf)?), + 3 => m.put_raw(index, String::read_from(buf)?), + 4 => m.put_raw(index, format::Component::read_from(buf)?), + 5 => m.put_raw(index, Option::::read_from(buf)?), + 6 => m.put_raw(index, bool::read_from(buf)?), 7 => m.put_raw(index, - [try!(f32::read_from(buf)), - try!(f32::read_from(buf)), - try!(f32::read_from(buf))]), - 8 => m.put_raw(index, try!(Position::read_from(buf))), + [f32::read_from(buf)?, + f32::read_from(buf)?, + f32::read_from(buf)?]), + 8 => m.put_raw(index, Position::read_from(buf)?), 9 => { - if try!(bool::read_from(buf)) { - m.put_raw(index, try!(Option::::read_from(buf))); + if bool::read_from(buf)? { + m.put_raw(index, Option::::read_from(buf)?); } else { m.put_raw::>(index, None); } } - 10 => m.put_raw(index, try!(protocol::VarInt::read_from(buf))), + 10 => m.put_raw(index, protocol::VarInt::read_from(buf)?), 11 => { - if try!(bool::read_from(buf)) { - m.put_raw(index, try!(Option::::read_from(buf))); + if bool::read_from(buf)? { + m.put_raw(index, Option::::read_from(buf)?); } else { m.put_raw::>(index, None); } } - 12 => m.put_raw(index, try!(protocol::VarInt::read_from(buf)).0 as u16), + 12 => m.put_raw(index, protocol::VarInt::read_from(buf)?.0 as u16), _ => return Err(protocol::Error::Err("unknown metadata type".to_owned())), } } @@ -106,76 +106,76 @@ impl Serializable for Metadata { fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { for (k, v) in &self.map { - try!((*k as u8).write_to(buf)); + (*k as u8).write_to(buf)?; match *v { Value::Byte(ref val) => { - try!(u8::write_to(&0, buf)); - try!(val.write_to(buf)); + u8::write_to(&0, buf)?; + val.write_to(buf)?; } Value::Int(ref val) => { - try!(u8::write_to(&1, buf)); - try!(protocol::VarInt(*val).write_to(buf)); + u8::write_to(&1, buf)?; + protocol::VarInt(*val).write_to(buf)?; } Value::Float(ref val) => { - try!(u8::write_to(&2, buf)); - try!(val.write_to(buf)); + u8::write_to(&2, buf)?; + val.write_to(buf)?; } Value::String(ref val) => { - try!(u8::write_to(&3, buf)); - try!(val.write_to(buf)); + u8::write_to(&3, buf)?; + val.write_to(buf)?; } Value::FormatComponent(ref val) => { - try!(u8::write_to(&4, buf)); - try!(val.write_to(buf)); + u8::write_to(&4, buf)?; + val.write_to(buf)?; } Value::OptionalItemStack(ref val) => { - try!(u8::write_to(&5, buf)); - try!(val.write_to(buf)); + u8::write_to(&5, buf)?; + val.write_to(buf)?; } Value::Bool(ref val) => { - try!(u8::write_to(&6, buf)); - try!(val.write_to(buf)); + u8::write_to(&6, buf)?; + val.write_to(buf)?; } Value::Vector(ref val) => { - try!(u8::write_to(&7, buf)); - try!(val[0].write_to(buf)); - try!(val[1].write_to(buf)); - try!(val[2].write_to(buf)); + u8::write_to(&7, buf)?; + val[0].write_to(buf)?; + val[1].write_to(buf)?; + val[2].write_to(buf)?; } Value::Position(ref val) => { - try!(u8::write_to(&8, buf)); - try!(val.write_to(buf)); + u8::write_to(&8, buf)?; + val.write_to(buf)?; } Value::OptionalPosition(ref val) => { - try!(u8::write_to(&9, buf)); - try!(val.is_some().write_to(buf)); - try!(val.write_to(buf)); + u8::write_to(&9, buf)?; + val.is_some().write_to(buf)?; + val.write_to(buf)?; } Value::Direction(ref val) => { - try!(u8::write_to(&10, buf)); - try!(val.write_to(buf)); + u8::write_to(&10, buf)?; + val.write_to(buf)?; } Value::OptionalUUID(ref val) => { - try!(u8::write_to(&11, buf)); - try!(val.is_some().write_to(buf)); - try!(val.write_to(buf)); + u8::write_to(&11, buf)?; + val.is_some().write_to(buf)?; + val.write_to(buf)?; } Value::Block(ref val) => { - try!(u8::write_to(&11, buf)); - try!(protocol::VarInt(*val as i32).write_to(buf)); + u8::write_to(&11, buf)?; + protocol::VarInt(*val as i32).write_to(buf)?; } } } - try!(u8::write_to(&0xFF, buf)); + u8::write_to(&0xFF, buf)?; Ok(()) } } impl fmt::Debug for Metadata { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "Metadata[ ")); + write!(f, "Metadata[ ")?; for (k, v) in &self.map { - try!(write!(f, "{:?}={:?}, ", k, v)); + write!(f, "{:?}={:?}, ", k, v)?; } write!(f, "]") } From cb9cf3ef708f20a01cba355b033be720fa3ca5ea Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 4 Nov 2018 11:48:03 -0800 Subject: [PATCH 36/47] Update to use crate:: for current crate, for Rust 2018 edition From `cargo fix --edition`, see https://rust-lang-nursery.github.io/edition-guide/print.html#the-crate-keyword-refers-to-the-current-crate --- protocol/src/item.rs | 4 ++-- protocol/src/types/metadata.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/protocol/src/item.rs b/protocol/src/item.rs index dfea1c6..19fa87c 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use nbt; -use protocol::{self, Serializable}; +use crate::nbt; +use crate::protocol::{self, Serializable}; use std::io; use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index d59ba51..5af4fcc 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -16,11 +16,11 @@ use std::collections::HashMap; use std::marker::PhantomData; use std::io; use std::fmt; -use protocol; -use protocol::Serializable; -use format; -use item; -use shared::Position; +use crate::protocol; +use crate::protocol::Serializable; +use crate::format; +use crate::item; +use crate::shared::Position; pub struct MetadataKey { index: i32, From 901e54772eacc0f53f536ee89c826d6d18752261 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 4 Nov 2018 13:43:30 -0800 Subject: [PATCH 37/47] Use field init shorthand, instead of x:x, just x, https://rust-lang-nursery.github.io/edition-guide/rust-2018/data-types/field-init-shorthand.html find src -name '*.rs' -exec perl -pe 's/\b(\w+): \1,/$1,/g' -i {} \; --- protocol/src/format.rs | 6 +++--- protocol/src/types/bit/map.rs | 2 +- protocol/src/types/metadata.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 88dba9c..79248d4 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -41,7 +41,7 @@ impl Component { if let Some(val) = v.as_str() { Component::Text(TextComponent { text: val.to_owned(), - modifier: modifier, + modifier, }) } else if v.get("text").is_some() { Component::Text(TextComponent::from_value(v, modifier)) @@ -49,7 +49,7 @@ impl Component { modifier.color = Some(Color::RGB(255, 0, 0)); Component::Text(TextComponent { text: "UNHANDLED".to_owned(), - modifier: modifier, + modifier, }) } } @@ -136,7 +136,7 @@ impl TextComponent { pub fn from_value(v: &serde_json::Value, modifier: Modifier) -> Self { TextComponent { text: v.get("text").unwrap().as_str().unwrap_or("").to_owned(), - modifier: modifier, + modifier, } } diff --git a/protocol/src/types/bit/map.rs b/protocol/src/types/bit/map.rs index 11979fe..2f86979 100644 --- a/protocol/src/types/bit/map.rs +++ b/protocol/src/types/bit/map.rs @@ -63,7 +63,7 @@ impl Map { Map { length: (bits.len()*64 + (size-1)) / size, bit_size: size, - bits: bits, + bits, } } diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 5af4fcc..228a034 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -31,7 +31,7 @@ impl MetadataKey { #[allow(dead_code)] fn new(index: i32) -> MetadataKey { MetadataKey { - index: index, + index, ty: PhantomData, } } From 9504be550f92535fc267d761ad853efcf5cc58bc Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 2 Dec 2018 12:29:05 -0800 Subject: [PATCH 38/47] Recognize translate text components, instead of showing "UNHANDLED" For example, if a server connection times out and you are kicked, Steven will now show disconnect.reason timeout, versus a non-descriptive UNHANDLED message. This text is supposed to be looked up in a translation table for localization, not yet supported, but showing the translation identifier is more informative than nothing. --- protocol/src/format.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/protocol/src/format.rs b/protocol/src/format.rs index 79248d4..29776bd 100644 --- a/protocol/src/format.rs +++ b/protocol/src/format.rs @@ -45,6 +45,9 @@ impl Component { }) } else if v.get("text").is_some() { Component::Text(TextComponent::from_value(v, modifier)) + } else if v.get("translate").is_some() { + // TODO: translations + Component::Text(TextComponent::new(v.get("translate").unwrap().as_str().unwrap())) } else { modifier.color = Some(Color::RGB(255, 0, 0)); Component::Text(TextComponent { 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 39/47] 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::*; From 7f2e2033cad5d9739c433202844c4a8f0dd1b27f Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 9 Dec 2018 12:03:55 -0800 Subject: [PATCH 40/47] 1.8.9 (47) multiprotocol support (#57) Protocol 47 (1.8.9-1.8) is the biggest multiprotocol (https://github.com/iceiix/steven/issues/18) change yet: * New chunk format (load_chunk18) * New metadata format (Metadata18) * New packets and changes to 13 packets References: http://wiki.vg/index.php?title=Protocol&oldid=7368 https://wiki.vg/Protocol_version_numbers#Versions_after_the_Netty_rewrite https://wiki.vg/Protocol_History#1.8 https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/1.8/protocol.json 1.8 chunk format: https://wiki.vg/index.php?title=Chunk_Format&oldid=6124 1.9 chunk format: https://wiki.vg/index.php?title=Chunk_Format&oldid=7411 1.8 vs 1.9: https://wiki.vg/index.php?title=Chunk_Format&diff=7411&oldid=6124 https://github.com/PrismarineJS/prismarine-chunk/blob/master/src/pc/1.8/section.js https://github.com/PrismarineJS/prismarine-chunk/blob/master/src/pc/1.8/chunk.js Details: * Add 1.8.9 packet IDs from https://github.com/iceiix/steven/pull/37 * Add ChunkDataBulk, parse the ChunkMeta and save data in Vec * Add EntityEquipment u16 variant, EntityStatus, ChunkData u16 variants * SpawnPlayer with added held item https://wiki.vg/Protocol_History#15w31a Removed Current Item short from Spawn Player (0x0C) * SpawnObject no UUID and optional velocity https://wiki.vg/index.php?title=Protocol&oldid=7368#Spawn_Object https://wiki.vg/Protocol_History#15w31a Added Entity UUID after entity ID to Spawn Object (0x0E) Spawn Object always sends velocity, even if data is 0 * SpawnMob no UUID variant https://wiki.vg/Protocol_History#15w31a Added Entity UUID after entity ID to Spawn Mob (0x0F) * Maps packet without tracking position boolean https://wiki.vg/index.php?title=Protocol&oldid=7368#Map https://wiki.vg/Protocol_History#15w34a Added tracking position boolean to Map (0x34) * Update Entity NBT was removed and Bossbar added (both 0x49) >1.8 https://wiki.vg/index.php?title=Protocol&oldid=7368#Update_Entity_NBT https://wiki.vg/Protocol_History#15w31a Removed Update Entity NBT Packet (0x49) Added Boss Bar packet (0x4 * Use entity without hands https://wiki.vg/index.php?title=Protocol&oldid=7368#Use_Entity https://wiki.vg/Protocol_History#15w31a Added VarInt enum for selected hand in Use Entity (0x02); only sent if type is interact or interact at * Player block placement, held item stack and face byte variant https://wiki.vg/index.php?title=Protocol&oldid=7368#Player_Block_Placement https://wiki.vg/Protocol_History#15w31a Face for Player Block Placement is now a VarInt enum instead of a byte Replaced held item (slot) with VarInt enum selected hand in Player Block Placement * Arm swing without hands, a packet with no fields, uses a ZST https://wiki.vg/index.php?title=Protocol&oldid=7368#Animation_2 https://github.com/iceiix/steven/pull/57#issuecomment-444289008 https://doc.rust-lang.org/nomicon/exotic-sizes.html * ClickWindow uses u8 mode, same as in 15w39c * ClientSettings without hands * SpectateTeleport is added before ResourcePackStatus * Copy load_chunk to load_chunk19 and load_chunk18 * 1.8 chunk reading implementation, load_chunk18 * Support both metadata formats, Metadata18/Metadata19 * Remove fmt::Debug * Implement formatting in MetadataBase and bounce through fmt::Debug --- protocol/src/types/metadata.rs | 205 +++++++++++++++++++++++++++++---- 1 file changed, 180 insertions(+), 25 deletions(-) diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 396b983..498cd01 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -38,32 +38,161 @@ impl MetadataKey { } } -pub struct Metadata { +pub struct Metadata18 { map: HashMap, } -impl Metadata { - pub fn new() -> Metadata { - Metadata { map: HashMap::new() } +pub struct Metadata19 { + map: HashMap, +} + +trait MetadataBase: fmt::Debug + Default { + fn map(&self) -> &HashMap; + fn map_mut(&mut self) -> &mut HashMap; + + fn get(&self, key: &MetadataKey) -> Option<&T> { + self.map().get(&key.index).map(T::unwrap) } - pub fn get(&self, key: &MetadataKey) -> Option<&T> { - self.map.get(&key.index).map(T::unwrap) - } - - pub fn put(&mut self, key: &MetadataKey, val: T) { - self.map.insert(key.index, val.wrap()); + fn put(&mut self, key: &MetadataKey, val: T) { + self.map_mut().insert(key.index, val.wrap()); } fn put_raw(&mut self, index: i32, val: T) { - self.map.insert(index, val.wrap()); + self.map_mut().insert(index, val.wrap()); + } + + fn fmt2(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Metadata[ ")?; + for (k, v) in self.map() { + write!(f, "{:?}={:?}, ", k, v)?; + } + write!(f, "]") } } -impl Serializable for Metadata { +impl MetadataBase for Metadata18 { + fn map(&self) -> &HashMap { &self.map } + fn map_mut(&mut self) -> &mut HashMap { &mut self.map } +} + +impl MetadataBase for Metadata19 { + fn map(&self) -> &HashMap { &self.map } + fn map_mut(&mut self) -> &mut HashMap { &mut self.map } +} + +impl Metadata18 { + pub fn new() -> Self { + Self { map: HashMap::new() } + } +} + +impl Metadata19 { + pub fn new() -> Self { + Self { map: HashMap::new() } + } +} + + + +impl Serializable for Metadata18 { fn read_from(buf: &mut R) -> Result { - let mut m = Metadata::new(); + let mut m = Self::new(); + loop { + let ty_index = u8::read_from(buf)? as i32; + if ty_index == 0x7f { + break; + } + let index = ty_index & 0x1f; + let ty = ty_index >> 5; + + match ty { + 0 => m.put_raw(index, i8::read_from(buf)?), + 1 => m.put_raw(index, i16::read_from(buf)?), + 2 => m.put_raw(index, i32::read_from(buf)?), + 3 => m.put_raw(index, f32::read_from(buf)?), + 4 => m.put_raw(index, String::read_from(buf)?), + 5 => m.put_raw(index, Option::::read_from(buf)?), + 6 => m.put_raw(index, + [i32::read_from(buf)?, + i32::read_from(buf)?, + i32::read_from(buf)?]), + 7 => m.put_raw(index, + [f32::read_from(buf)?, + f32::read_from(buf)?, + f32::read_from(buf)?]), + _ => return Err(protocol::Error::Err("unknown metadata type".to_owned())), + } + } + Ok(m) + } + + fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { + for (k, v) in &self.map { + if (*k as u8) > 0x1f { + panic!("write metadata index {:x} > 0x1f", *k as u8); + } + + let ty_index: u8 = *k as u8; + const TYPE_SHIFT: usize = 5; + + match *v + { + Value::Byte(ref val) => { + u8::write_to(&(ty_index | (0 << TYPE_SHIFT)), buf)?; + val.write_to(buf)?; + } + Value::Short(ref val) => { + u8::write_to(&(ty_index | (1 << TYPE_SHIFT)), buf)?; + val.write_to(buf)?; + } + + Value::Int(ref val) => { + u8::write_to(&(ty_index | (2 << TYPE_SHIFT)), buf)?; + val.write_to(buf)?; + } + Value::Float(ref val) => { + u8::write_to(&(ty_index | (3 << TYPE_SHIFT)), buf)?; + val.write_to(buf)?; + } + Value::String(ref val) => { + u8::write_to(&(ty_index | (4 << TYPE_SHIFT)), buf)?; + val.write_to(buf)?; + } + Value::OptionalItemStack(ref val) => { + u8::write_to(&(ty_index | (5 << TYPE_SHIFT)), buf)?; + val.write_to(buf)?; + } + Value::Vector(ref val) => { + u8::write_to(&(ty_index | (6 << TYPE_SHIFT)), buf)?; + val[0].write_to(buf)?; + val[1].write_to(buf)?; + val[2].write_to(buf)?; + } + Value::Rotation(ref val) => { + u8::write_to(&(ty_index | (7 << TYPE_SHIFT)), buf)?; + val[0].write_to(buf)?; + val[1].write_to(buf)?; + val[2].write_to(buf)?; + } + + Value::FormatComponent(_) | Value::Bool(_) | Value::Position(_) | + Value::OptionalPosition(_) | Value::Direction(_) | Value::OptionalUUID(_) | + Value::Block(_) | Value::NBTTag(_) => { + panic!("attempted to write 1.9+ metadata to 1.8"); + } + } + } + u8::write_to(&0x7f, buf)?; + Ok(()) + } +} + +impl Serializable for Metadata19 { + + fn read_from(buf: &mut R) -> Result { + let mut m = Self::new(); loop { let index = u8::read_from(buf)? as i32; if index == 0xFF { @@ -179,6 +308,7 @@ impl Serializable for Metadata { // TODO: write NBT tags metadata //nbt::Tag(*val).write_to(buf)?; } + _ => panic!("unexpected metadata"), } } u8::write_to(&0xFF, buf)?; @@ -186,25 +316,25 @@ impl Serializable for Metadata { } } -impl fmt::Debug for Metadata { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Metadata[ ")?; - for (k, v) in &self.map { - write!(f, "{:?}={:?}, ", k, v)?; - } - write!(f, "]") +// TODO: is it possible to implement these traits on MetadataBase instead? +impl fmt::Debug for Metadata19 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt2(f) } } +impl fmt::Debug for Metadata18 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt2(f) } } + +impl Default for Metadata19 { + fn default() -> Self { + Self::new() } } - -impl Default for Metadata { - fn default() -> Metadata { - Metadata::new() +impl Default for Metadata18 { + fn default() -> Self { + Self::new() } } #[derive(Debug)] pub enum Value { Byte(i8), + Short(i16), Int(i32), Float(f32), String(String), @@ -212,6 +342,7 @@ pub enum Value { OptionalItemStack(Option), Bool(bool), Vector([f32; 3]), + Rotation([i32; 3]), Position(Position), OptionalPosition(Option), Direction(protocol::VarInt), // TODO: Proper type @@ -237,6 +368,18 @@ impl MetaValue for i8 { } } +impl MetaValue for i16 { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Short(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Short(self) + } +} + impl MetaValue for i32 { fn unwrap(value: &Value) -> &Self { match *value { @@ -309,6 +452,18 @@ impl MetaValue for bool { } } +impl MetaValue for [i32; 3] { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Rotation(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Rotation(self) + } +} + impl MetaValue for [f32; 3] { fn unwrap(value: &Value) -> &Self { match *value { @@ -406,7 +561,7 @@ mod test { #[test] fn basic() { - let mut m = Metadata::new(); + let mut m = Metadata19::new(); m.put(&TEST, "Hello world".to_owned()); From e28946b691b241cedaf62bcb5932b6212e3ae31f Mon Sep 17 00:00:00 2001 From: ice_iix Date: Tue, 11 Dec 2018 18:18:25 -0800 Subject: [PATCH 41/47] Add protocol version global mutable to merge Metadata18/19 into one Cleans up https://github.com/iceiix/steven/pull/57 1.8.9 (47) multiprotocol support which added too much code duplication, Metadata19 vs Metadata18, and different packets for each, the only difference being how it was parsed. Instead, switch back to using only one Metadata implementation, but with parsing conditionalized on a new global mutable: SUPPORTED_PROTOCOL_VERSION. Accessing global mutable state is unsafe but it is only set when initializing the connection, and only read when deep enough in the code where it is not feasible to pass otherwise. More elegant, worth it. --- protocol/src/types/metadata.rs | 118 ++++++++++++++------------------- 1 file changed, 49 insertions(+), 69 deletions(-) diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 498cd01..44ee0a7 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -38,66 +38,28 @@ impl MetadataKey { } } -pub struct Metadata18 { +pub struct Metadata { map: HashMap, } -pub struct Metadata19 { - map: HashMap, -} - -trait MetadataBase: fmt::Debug + Default { - fn map(&self) -> &HashMap; - fn map_mut(&mut self) -> &mut HashMap; - - fn get(&self, key: &MetadataKey) -> Option<&T> { - self.map().get(&key.index).map(T::unwrap) +impl Metadata { + pub fn new() -> Metadata { + Metadata { map: HashMap::new() } } - fn put(&mut self, key: &MetadataKey, val: T) { - self.map_mut().insert(key.index, val.wrap()); + pub fn get(&self, key: &MetadataKey) -> Option<&T> { + self.map.get(&key.index).map(T::unwrap) + } + + pub fn put(&mut self, key: &MetadataKey, val: T) { + self.map.insert(key.index, val.wrap()); } fn put_raw(&mut self, index: i32, val: T) { - self.map_mut().insert(index, val.wrap()); + self.map.insert(index, val.wrap()); } - fn fmt2(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Metadata[ ")?; - for (k, v) in self.map() { - write!(f, "{:?}={:?}, ", k, v)?; - } - write!(f, "]") - } -} - -impl MetadataBase for Metadata18 { - fn map(&self) -> &HashMap { &self.map } - fn map_mut(&mut self) -> &mut HashMap { &mut self.map } -} - -impl MetadataBase for Metadata19 { - fn map(&self) -> &HashMap { &self.map } - fn map_mut(&mut self) -> &mut HashMap { &mut self.map } -} - -impl Metadata18 { - pub fn new() -> Self { - Self { map: HashMap::new() } - } -} - -impl Metadata19 { - pub fn new() -> Self { - Self { map: HashMap::new() } - } -} - - - -impl Serializable for Metadata18 { - - fn read_from(buf: &mut R) -> Result { + fn read_from18(buf: &mut R) -> Result { let mut m = Self::new(); loop { let ty_index = u8::read_from(buf)? as i32; @@ -128,7 +90,7 @@ impl Serializable for Metadata18 { Ok(m) } - fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { + fn write_to18(&self, buf: &mut W) -> Result<(), protocol::Error> { for (k, v) in &self.map { if (*k as u8) > 0x1f { panic!("write metadata index {:x} > 0x1f", *k as u8); @@ -177,9 +139,7 @@ impl Serializable for Metadata18 { val[2].write_to(buf)?; } - Value::FormatComponent(_) | Value::Bool(_) | Value::Position(_) | - Value::OptionalPosition(_) | Value::Direction(_) | Value::OptionalUUID(_) | - Value::Block(_) | Value::NBTTag(_) => { + _ => { panic!("attempted to write 1.9+ metadata to 1.8"); } } @@ -187,11 +147,8 @@ impl Serializable for Metadata18 { u8::write_to(&0x7f, buf)?; Ok(()) } -} -impl Serializable for Metadata19 { - - fn read_from(buf: &mut R) -> Result { + fn read_from19(buf: &mut R) -> Result { let mut m = Self::new(); loop { let index = u8::read_from(buf)? as i32; @@ -243,7 +200,7 @@ impl Serializable for Metadata19 { Ok(m) } - fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { + fn write_to19(&self, buf: &mut W) -> Result<(), protocol::Error> { for (k, v) in &self.map { (*k as u8).write_to(buf)?; match *v { @@ -316,18 +273,41 @@ impl Serializable for Metadata19 { } } -// TODO: is it possible to implement these traits on MetadataBase instead? -impl fmt::Debug for Metadata19 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt2(f) } } -impl fmt::Debug for Metadata18 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt2(f) } } +impl Serializable for Metadata { + fn read_from(buf: &mut R) -> Result { + let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION }; -impl Default for Metadata19 { - fn default() -> Self { - Self::new() + if protocol_version >= 74 { + Metadata::read_from19(buf) + } else { + Metadata::read_from18(buf) + } + } + + fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { + let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION }; + + if protocol_version >= 74 { + self.write_to19(buf) + } else { + self.write_to18(buf) + } } } -impl Default for Metadata18 { - fn default() -> Self { - Self::new() + +impl fmt::Debug for Metadata { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Metadata[ ")?; + for (k, v) in &self.map { + write!(f, "{:?}={:?}, ", k, v)?; + } + write!(f, "]") + } +} + +impl Default for Metadata { + fn default() -> Metadata { + Metadata::new() } } @@ -561,7 +541,7 @@ mod test { #[test] fn basic() { - let mut m = Metadata19::new(); + let mut m = Metadata::new(); m.put(&TEST, "Hello world".to_owned()); From 37e6d962ec974dddf07285c8397aee38633785c3 Mon Sep 17 00:00:00 2001 From: iceiix <43691553+iceiix@users.noreply.github.com> Date: Sat, 15 Dec 2018 19:56:54 -0800 Subject: [PATCH 42/47] 1.7.10 (5) multiprotocol support (#64) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds 1.7.10 protocol version 5 support, a major update with significant changes. Expands https://github.com/iceiix/steven/issues/18 Enhance protocol support * Add v1_7_10 protocol packet structures and IDs * EncryptionRequest/Response i16 variant in login protocol * 1.7.10 slot NBT data parsing * Support both 1.7/1.8+ item::Stack in read_from, using if protocol_verson * 1.7.10 chunk format support, ChunkDataBulk_17 and ChunkData_17 * Extract dirty_chunks_by_bitmask from load_chunks17/18/19 * Implement keepalive i32 handler * Send PlayerPositionLook_HeadY * Send PlayerBlockPlacement_u8_Item_u8y * Handle JoinGame_i8_NoDebug * Handle SpawnPlayer_i32_HeldItem_String * BlockChange_u8, MultiBlockChange_i16, UpdateBlockEntity_Data, EntityMove_i8_i32_NoGround, EntityLook_i32_NoGround, EntityLookAndMove_i8_i32_NoGround * UpdateSign_u16, PlayerInfo_String, EntityDestroy_u8, EntityTeleport_i32_i32_NoGround * Send feet_y = head_y - 1.62, fixes Illegal stance https://wiki.vg/index.php?title=Protocol&oldid=6003#Player_Position > Updates the players XYZ position on the server. If HeadY - FeetY is less than 0.1 or greater than 1.65, the stance is illegal and the client will be kicked with the message “Illegal Stance”. > Absolute feet position, normally HeadY - 1.62. Used to modify the players bounding box when going up stairs, crouching, etc… * Set on_ground = true in entity teleport, fixes bouncing * Implement block change, fix metadata/id packing, bounce _u8 through on_block_change * Implement on_multi_block_change_u16, used with explosions --- protocol/src/item.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/protocol/src/item.rs b/protocol/src/item.rs index 19fa87c..7ed18d6 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -43,11 +43,32 @@ impl Serializable for Option { if id == -1 { return Ok(None); } + let count = buf.read_u8()? as isize; + let damage = buf.read_i16::()? as isize; + + let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION }; + + let tag: Option = if protocol_version >= 47 { + Serializable::read_from(buf)? + } else { + // 1.7 uses a different slot data format described on https://wiki.vg/index.php?title=Slot_Data&diff=6056&oldid=4753 + let tag_size = buf.read_i16::()?; + if tag_size != -1 { + for _ in 0..tag_size { + let _ = buf.read_u8()?; + } + // TODO: decompress zlib NBT for 1.7 + None + } else { + None + } + }; + Ok(Some(Stack { id: id as isize, - count: buf.read_u8()? as isize, - damage: buf.read_i16::()? as isize, - tag: Serializable::read_from(buf)?, + count, + damage, + tag, })) } fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { @@ -56,6 +77,7 @@ impl Serializable for Option { buf.write_i16::(val.id as i16)?; buf.write_u8(val.count as u8)?; buf.write_i16::(val.damage as i16)?; + // TODO: compress zlib NBT if 1.7 val.tag.write_to(buf)?; } None => buf.write_i16::(-1)?, From 68441320e8fcb6c0cfe2b8337e831d6692ab0c43 Mon Sep 17 00:00:00 2001 From: iceiix <43691553+iceiix@users.noreply.github.com> Date: Fri, 28 Dec 2018 21:11:42 -0800 Subject: [PATCH 43/47] 1.13.2 (404) multiprotocol support (#67) Adds support for 1.13.2 protocol (404) Expands https://github.com/iceiix/steven/issues/18 Enhance protocol support Metadata: * Support 1.13.2 slot data format, bool and varint item id, optional damage (moved to NBT) https://wiki.vg/index.php?title=Slot_Data&type=revision&diff=14363&oldid=7835 Packets: * Add 1.13.2 packets, and implement all the command data parsers https://wiki.vg/Command_Data#Parsers * Send new plugin channel minecraft:brand https://wiki.vg/Plugin_channels#minecraft:brand * Add 1.13.2 metadata format, with shifted IDs https://wiki.vg/Entity_metadata#Entity_Metadata_Format * Implement particle entity metadata * Add structures for 16 new packets Blocks: The Flattening: * Assign flattened IDs in correct order using new 'offset' macro token * Assign hierarchical (pre-flattening) block IDs sequentially by counting Some data * Split VANILLA_ID_MAP into flat/hier struct, to support before and after the flattening * Extend travis build time to 20 minutes because the blocks macro takes a long time * Support both flat/hier blocks by passing protocol_version to by_vanilla_id Add block states and offsets for all blocks, replacing metadata for 1.13+: * Add stripped logs and what was Log2 to Log * Add the Wood blocks, should be called bark, previously Axis::None Log * Add leaves distance and offset * Add jungle/acacia to Leaves moved from Leaves2 * Add dispenser offsets, direction * Add note block states * Add offset None to Missing253 and Missing254, no holes in block states of 1.13.2 * Add bed colors * Add seagrass, tall seagrass, remove redundant deadgrass, and piston offset * Add torch, TNT, fire offsets, remove slabs * Add furnance offset, merges lit into a property * Add pressure plate offsets, new pressure plates, redstone ore/lit merged * Add lever offsets, new directions from ceiling/floor, rename LeverDirections * Add redstone torch offsets, new blocks since lit/unlit is now merged, and standing/wall is split * Change lever to split face/facing, rm LeverDirection, add AttachedFace * Add stone button offsets, face/facing similar to lever * Move face/facing data and variant to AttachedFace, reuse for lever/stonebutton * Add data_with_facing_and_powered() to AttachedFace, for lever/stonebutton * Add wooden button offsets each wood * Add pumpkin without a face * Add carved pumpkin, portal offsets * Add lit pumpkin (as jack-o-lantern) offsets after carved pumpkin * Add repeater offsets, merged into Repeater * Change brown mushroom block to booleans instead of MushroomVariant * Add mushroom block offsets, red/brown mushroom blocks, and a new mushroom stem block * Add command block, cobblestone walls, and flower pot offsets Empty flower pot, and potted plants including saplings. Rename variant DarkOak to DarkOakSaplings because it is a sapling, and remove the duplicate Dandelion variant which causes duplicate blocks. * Increase recursion limit in steven_blocks * Add colored banner offsets * Add wooden slab including double slab, in a different position for pre-1.13 and 1.13 * StoneSlabVariant::Wood -> StoneSlabVariant::PetrifiedWood * Add fence_gate_offset() for wooden fence gates * Add frosted ice age, offset * Add new blocks: kelp, turtle egg, coral, coral fans, sea pickle, blue ice, smooth stone * Add new blocks: conduit, void air, cave aid, bubble column, last of the 1.13 blocks --- protocol/src/item.rs | 32 +++- protocol/src/types/metadata.rs | 299 ++++++++++++++++++++++++++++++++- 2 files changed, 322 insertions(+), 9 deletions(-) diff --git a/protocol/src/item.rs b/protocol/src/item.rs index 7ed18d6..9d791e9 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -21,7 +21,7 @@ use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; pub struct Stack { id: isize, count: isize, - damage: isize, + damage: Option, tag: Option, } @@ -31,7 +31,7 @@ impl Default for Stack { Stack { id: -1, count: 0, - damage: 0, + damage: None, tag: None, } } @@ -39,14 +39,31 @@ impl Default for Stack { impl Serializable for Option { fn read_from(buf: &mut R) -> Result, protocol::Error> { - let id = buf.read_i16::()?; + let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION }; + + if protocol_version >= 404 { + let present = buf.read_u8()? != 0; + if !present { + return Ok(None) + } + } + + let id = if protocol_version >= 404 { + protocol::VarInt::read_from(buf)?.0 as isize + } else { + buf.read_i16::()? as isize + }; + if id == -1 { return Ok(None); } let count = buf.read_u8()? as isize; - let damage = buf.read_i16::()? as isize; - - let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION }; + let damage = if protocol_version >= 404 { + // 1.13.2+ stores damage in the NBT + None + } else { + Some(buf.read_i16::()? as isize) + }; let tag: Option = if protocol_version >= 47 { Serializable::read_from(buf)? @@ -74,9 +91,10 @@ impl Serializable for Option { fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { match *self { Some(ref val) => { + // TODO: if protocol_version >= 404, send present and id varint, no damage, for 1.13.2 buf.write_i16::(val.id as i16)?; buf.write_u8(val.count as u8)?; - buf.write_i16::(val.damage as i16)?; + buf.write_i16::(val.damage.unwrap_or(0) as i16)?; // TODO: compress zlib NBT if 1.7 val.tag.write_to(buf)?; } diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index 44ee0a7..a5e8a3e 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -18,6 +18,7 @@ use std::io; use std::fmt; use crate::protocol; use crate::protocol::Serializable; +use crate::protocol::LenPrefixed; use crate::format; use crate::item; use crate::shared::Position; @@ -271,13 +272,151 @@ impl Metadata { u8::write_to(&0xFF, buf)?; Ok(()) } + + fn read_from113(buf: &mut R) -> Result { + let mut m = Self::new(); + loop { + let index = u8::read_from(buf)? as i32; + if index == 0xFF { + break; + } + 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), + 2 => m.put_raw(index, f32::read_from(buf)?), + 3 => m.put_raw(index, String::read_from(buf)?), + 4 => m.put_raw(index, format::Component::read_from(buf)?), + 5 => m.put_raw(index, LenPrefixed::::read_from(buf)?), + 6 => m.put_raw(index, Option::::read_from(buf)?), + 7 => m.put_raw(index, bool::read_from(buf)?), + 8 => m.put_raw(index, + [f32::read_from(buf)?, + f32::read_from(buf)?, + f32::read_from(buf)?]), + 9 => m.put_raw(index, Position::read_from(buf)?), + 10 => { + if bool::read_from(buf)? { + m.put_raw(index, Option::::read_from(buf)?); + } else { + m.put_raw::>(index, None); + } + } + 11 => m.put_raw(index, protocol::VarInt::read_from(buf)?), + 12 => { + if bool::read_from(buf)? { + m.put_raw(index, Option::::read_from(buf)?); + } else { + m.put_raw::>(index, None); + } + } + 13 => m.put_raw(index, protocol::VarInt::read_from(buf)?.0 as u16), + 14 => { + 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)); + } + } + 15 => panic!("TODO: particle"), + _ => return Err(protocol::Error::Err("unknown metadata type".to_owned())), + } + } + Ok(m) + } + + fn write_to113(&self, buf: &mut W) -> Result<(), protocol::Error> { + for (k, v) in &self.map { + (*k as u8).write_to(buf)?; + match *v { + Value::Byte(ref val) => { + u8::write_to(&0, buf)?; + val.write_to(buf)?; + } + Value::Int(ref val) => { + u8::write_to(&1, buf)?; + protocol::VarInt(*val).write_to(buf)?; + } + Value::Float(ref val) => { + u8::write_to(&2, buf)?; + val.write_to(buf)?; + } + Value::String(ref val) => { + u8::write_to(&3, buf)?; + val.write_to(buf)?; + } + Value::FormatComponent(ref val) => { + u8::write_to(&4, buf)?; + val.write_to(buf)?; + } + Value::OptionalFormatComponent(ref val) => { + u8::write_to(&5, buf)?; + val.write_to(buf)?; + } + Value::OptionalItemStack(ref val) => { + u8::write_to(&6, buf)?; + val.write_to(buf)?; + } + Value::Bool(ref val) => { + u8::write_to(&7, buf)?; + val.write_to(buf)?; + } + Value::Vector(ref val) => { + u8::write_to(&8, buf)?; + val[0].write_to(buf)?; + val[1].write_to(buf)?; + val[2].write_to(buf)?; + } + Value::Position(ref val) => { + u8::write_to(&9, buf)?; + val.write_to(buf)?; + } + Value::OptionalPosition(ref val) => { + u8::write_to(&10, buf)?; + val.is_some().write_to(buf)?; + val.write_to(buf)?; + } + Value::Direction(ref val) => { + u8::write_to(&11, buf)?; + val.write_to(buf)?; + } + Value::OptionalUUID(ref val) => { + u8::write_to(&12, buf)?; + val.is_some().write_to(buf)?; + val.write_to(buf)?; + } + Value::Block(ref val) => { + u8::write_to(&13, buf)?; + protocol::VarInt(*val as i32).write_to(buf)?; + } + Value::NBTTag(ref _val) => { + u8::write_to(&14, buf)?; + // TODO: write NBT tags metadata + //nbt::Tag(*val).write_to(buf)?; + } + Value::Particle(ref val) => { + u8::write_to(&15, buf)?; + val.write_to(buf)?; + } + _ => panic!("unexpected metadata"), + } + } + u8::write_to(&0xFF, buf)?; + Ok(()) + } + + } impl Serializable for Metadata { fn read_from(buf: &mut R) -> Result { let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION }; - if protocol_version >= 74 { + if protocol_version >= 404 { + Metadata::read_from113(buf) + } else if protocol_version >= 74 { Metadata::read_from19(buf) } else { Metadata::read_from18(buf) @@ -287,7 +426,9 @@ impl Serializable for Metadata { fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION }; - if protocol_version >= 74 { + if protocol_version >= 404 { + self.write_to113(buf) + } else if protocol_version >= 74 { self.write_to19(buf) } else { self.write_to18(buf) @@ -319,6 +460,7 @@ pub enum Value { Float(f32), String(String), FormatComponent(format::Component), + OptionalFormatComponent(LenPrefixed), OptionalItemStack(Option), Bool(bool), Vector([f32; 3]), @@ -329,6 +471,146 @@ pub enum Value { OptionalUUID(Option), Block(u16), // TODO: Proper type NBTTag(nbt::NamedTag), + Particle(ParticleData), +} + +#[derive(Debug)] +pub enum ParticleData { + AmbientEntityEffect, + AngryVillager, + Barrier, + Block { + block_state: protocol::VarInt, + }, + Bubble, + Cloud, + Crit, + DamageIndicator, + DragonBreath, + DrippingLava, + DrippingWater, + Dust { + red: f32, + green: f32, + blue: f32, + scale: f32, + }, + Effect, + ElderGuardian, + EnchantedHit, + Enchant, + EndRod, + EntityEffect, + ExplosionEmitter, + Explosion, + FallingDust { + block_state: protocol::VarInt, + }, + Firework, + Fishing, + Flame, + HappyVillager, + Heart, + InstantEffect, + Item { + item: Option, + }, + ItemSlime, + ItemSnowball, + LargeSmoke, + Lava, + Mycelium, + Note, + Poof, + Portal, + Rain, + Smoke, + Spit, + SquidInk, + SweepAttack, + TotemOfUndying, + Underwater, + Splash, + Witch, + BubblePop, + CurrentDown, + BubbleColumnUp, + Nautilus, + Dolphin, +} + +impl Serializable for ParticleData { + fn read_from(buf: &mut R) -> Result { + let id = protocol::VarInt::read_from(buf)?.0; + Ok(match id { + 0 => ParticleData::AmbientEntityEffect, + 1 => ParticleData::AngryVillager, + 2 => ParticleData::Barrier, + 3 => ParticleData::Block { + block_state: Serializable::read_from(buf)? + }, + 4 => ParticleData::Bubble, + 5 => ParticleData::Cloud, + 6 => ParticleData::Crit, + 7 => ParticleData::DamageIndicator, + 8 => ParticleData::DragonBreath, + 9 => ParticleData::DrippingLava, + 10 => ParticleData::DrippingWater, + 11 => ParticleData::Dust { + red: Serializable::read_from(buf)?, + green: Serializable::read_from(buf)?, + blue: Serializable::read_from(buf)?, + scale: Serializable::read_from(buf)?, + }, + 12 => ParticleData::Effect, + 13 => ParticleData::ElderGuardian, + 14 => ParticleData::EnchantedHit, + 15 => ParticleData::Enchant, + 16 => ParticleData::EndRod, + 17 => ParticleData::EntityEffect, + 18 => ParticleData::ExplosionEmitter, + 19 => ParticleData::Explosion, + 20 => ParticleData::FallingDust { + block_state: Serializable::read_from(buf)?, + }, + 21 => ParticleData::Firework, + 22 => ParticleData::Fishing, + 23 => ParticleData::Flame, + 24 => ParticleData::HappyVillager, + 25 => ParticleData::Heart, + 26 => ParticleData::InstantEffect, + 27 => ParticleData::Item { + item: Serializable::read_from(buf)?, + }, + 28 => ParticleData::ItemSlime, + 29 => ParticleData::ItemSnowball, + 30 => ParticleData::LargeSmoke, + 31 => ParticleData::Lava, + 32 => ParticleData::Mycelium, + 33 => ParticleData::Note, + 34 => ParticleData::Poof, + 35 => ParticleData::Portal, + 36 => ParticleData::Rain, + 37 => ParticleData::Smoke, + 38 => ParticleData::Spit, + 39 => ParticleData::SquidInk, + 40 => ParticleData::SweepAttack, + 41 => ParticleData::TotemOfUndying, + 42 => ParticleData::Underwater, + 43 => ParticleData::Splash, + 44 => ParticleData::Witch, + 45 => ParticleData::BubblePop, + 46 => ParticleData::CurrentDown, + 47 => ParticleData::BubbleColumnUp, + 48 => ParticleData::Nautilus, + 49 => ParticleData::Dolphin, + _ => panic!("unrecognized particle data id {}", id), + }) + } + + fn write_to(&self, _buf: &mut W) -> Result<(), protocol::Error> { + unimplemented!() + } } pub trait MetaValue { @@ -408,6 +690,19 @@ impl MetaValue for format::Component { } } +impl MetaValue for LenPrefixed { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::OptionalFormatComponent(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::OptionalFormatComponent(self) + } +} + + impl MetaValue for Option { fn unwrap(value: &Value) -> &Self { match *value { From 264bf6084e20cd9a753aba2973cdcee80993eed7 Mon Sep 17 00:00:00 2001 From: iceiix <43691553+iceiix@users.noreply.github.com> Date: Thu, 10 Jan 2019 17:21:19 -0800 Subject: [PATCH 44/47] Add 18w50a (451) multiprotocol support (#79) Adds 18w50a (451) multiprotocol support, last snapshot of 2018 Reference: https://wiki.vg/index.php?title=Pre-release_protocol&oldid=14491 * Use v18w50a module for protocol * Add blasting, smoking, and suspicious stew recipe types * Add entity tags to tags packet * Add chunk data packet variant with height map * Add update light packet * Add chunk format parsing with block_count, without skylights, conditionalize on protocol_version >= 451 * Add villager data entity metadata type parsing https://wiki.vg/Pre-release_protocol#Entity_Metadata * Add open book and entity sound effect packets --- protocol/src/types/metadata.rs | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index a5e8a3e..cb390ff 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -321,6 +321,7 @@ impl Metadata { } } 15 => panic!("TODO: particle"), + 16 => m.put_raw(index, VillagerData::read_from(buf)?), _ => return Err(protocol::Error::Err("unknown metadata type".to_owned())), } } @@ -400,6 +401,10 @@ impl Metadata { u8::write_to(&15, buf)?; val.write_to(buf)?; } + Value::Villager(ref val) => { + u8::write_to(&16, buf)?; + val.write_to(buf)?; + } _ => panic!("unexpected metadata"), } } @@ -472,6 +477,7 @@ pub enum Value { Block(u16), // TODO: Proper type NBTTag(nbt::NamedTag), Particle(ParticleData), + Villager(VillagerData), } #[derive(Debug)] @@ -613,6 +619,27 @@ impl Serializable for ParticleData { } } +#[derive(Debug)] +pub struct VillagerData { + villager_type: protocol::VarInt, + profession: protocol::VarInt, + level: protocol::VarInt, +} + +impl Serializable for VillagerData { + fn read_from(buf: &mut R) -> Result { + let villager_type = protocol::VarInt::read_from(buf)?; + let profession = protocol::VarInt::read_from(buf)?; + let level = protocol::VarInt::read_from(buf)?; + Ok(VillagerData { villager_type, profession, level }) + } + + fn write_to(&self, _buf: &mut W) -> Result<(), protocol::Error> { + unimplemented!() + } +} + + pub trait MetaValue { fn unwrap(_: &Value) -> &Self; fn wrap(self) -> Value; @@ -823,6 +850,18 @@ impl MetaValue for nbt::NamedTag { } } +impl MetaValue for VillagerData { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Villager(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Villager(self) + } +} + #[cfg(test)] mod test { use super::*; From 4f4533411e9f4f90678f45dbcff38c4b14c8ab97 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sat, 4 May 2019 16:01:28 -0700 Subject: [PATCH 45/47] 1.14 protocol support (477) (#132). Closes #72 Adds 1.14 (477) protocol support, based on: https://wiki.vg/index.php?title=Pre-release_protocol&oldid=14723 * New packets: SetDifficulty, LockDifficulty, UpdateJigsawBlock, UpdateViewPosition, UpdateViewDistance * New metadata: Optional VarInt (17) and Pose (18) * Add new join game variant with view distance, without difficulty * Add new server difficulty variant, with locked boolean * Implement recipe parsing changes, add stonecutting recipe type --- protocol/src/types/metadata.rs | 75 ++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index cb390ff..e27e043 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -322,6 +322,14 @@ impl Metadata { } 15 => panic!("TODO: particle"), 16 => m.put_raw(index, VillagerData::read_from(buf)?), + 17 => { + if bool::read_from(buf)? { + m.put_raw(index, Option::::read_from(buf)?); + } else { + m.put_raw::>(index, None); + } + }, + 18 => m.put_raw(index, PoseData::read_from(buf)?), _ => return Err(protocol::Error::Err("unknown metadata type".to_owned())), } } @@ -405,6 +413,14 @@ impl Metadata { u8::write_to(&16, buf)?; val.write_to(buf)?; } + Value::OptionalVarInt(ref val) => { + u8::write_to(&17, buf)?; + val.write_to(buf)?; + } + Value::Pose(ref val) => { + u8::write_to(&18, buf)?; + val.write_to(buf)?; + } _ => panic!("unexpected metadata"), } } @@ -478,6 +494,8 @@ pub enum Value { NBTTag(nbt::NamedTag), Particle(ParticleData), Villager(VillagerData), + OptionalVarInt(Option), + Pose(PoseData), } #[derive(Debug)] @@ -639,6 +657,38 @@ impl Serializable for VillagerData { } } +#[derive(Debug)] +pub enum PoseData { + Standing, + FallFlying, + Sleeping, + Swimming, + SpinAttack, + Sneaking, + Dying, +} + +impl Serializable for PoseData { + fn read_from(buf: &mut R) -> Result { + let n = protocol::VarInt::read_from(buf)?; + Ok(match n.0 { + 0 => PoseData::Standing, + 1 => PoseData::FallFlying, + 2 => PoseData::Sleeping, + 3 => PoseData::Swimming, + 4 => PoseData::SpinAttack, + 5 => PoseData::Sneaking, + 6 => PoseData::Dying, + _ => panic!("unknown pose data: {}", n.0), + }) + } + + fn write_to(&self, _buf: &mut W) -> Result<(), protocol::Error> { + unimplemented!() + } +} + + pub trait MetaValue { fn unwrap(_: &Value) -> &Self; @@ -862,6 +912,31 @@ impl MetaValue for VillagerData { } } +impl MetaValue for Option { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::OptionalVarInt(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::OptionalVarInt(self) + } +} + +impl MetaValue for PoseData { + fn unwrap(value: &Value) -> &Self { + match *value { + Value::Pose(ref val) => val, + _ => panic!("incorrect key"), + } + } + fn wrap(self) -> Value { + Value::Pose(self) + } +} + + #[cfg(test)] mod test { use super::*; From f15ece0377f4922cc726541850b109d10f1e8ad9 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Sun, 12 May 2019 14:08:53 -0700 Subject: [PATCH 46/47] Replace read_to_string -> read_to_end to improve UTF-8 deserialization See https://github.com/iceiix/stevenarella/commit/c1692e950aceccb9872478ed43f65848d90dd347 There are two more instances, encountered when debugging #148 > Instead of read_to_string(), use read_to_end() to read into a buffer, > then convert using String::from_utf8() and unwrap it. This gives a > better error message when UTF-8 fails to decode. which includes the offending bytes that can't be converted --- protocol/src/nbt/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/protocol/src/nbt/mod.rs b/protocol/src/nbt/mod.rs index e72fad6..37c3eca 100644 --- a/protocol/src/nbt/mod.rs +++ b/protocol/src/nbt/mod.rs @@ -304,7 +304,8 @@ pub fn write_string(buf: &mut W, s: &str) -> Result<(), protocol:: pub fn read_string(buf: &mut R) -> Result { let len: i16 = buf.read_i16::()?; - let mut ret = String::new(); - buf.take(len as u64).read_to_string(&mut ret)?; + let mut bytes = Vec::::new(); + buf.take(len as u64).read_to_end(&mut bytes)?; + let ret = String::from_utf8(bytes).unwrap(); Result::Ok(ret) } From e834ee2f53533cb2c12771516736fdb4970fddf1 Mon Sep 17 00:00:00 2001 From: ice_iix Date: Wed, 8 Jan 2020 18:57:57 -0800 Subject: [PATCH 47/47] protocol: atomics replace unsafe for version/debug. Closes #261 --- protocol/src/item.rs | 2 +- protocol/src/types/metadata.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/protocol/src/item.rs b/protocol/src/item.rs index 9d791e9..8aa6ab4 100644 --- a/protocol/src/item.rs +++ b/protocol/src/item.rs @@ -39,7 +39,7 @@ impl Default for Stack { impl Serializable for Option { fn read_from(buf: &mut R) -> Result, protocol::Error> { - let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION }; + let protocol_version = protocol::current_protocol_version(); if protocol_version >= 404 { let present = buf.read_u8()? != 0; diff --git a/protocol/src/types/metadata.rs b/protocol/src/types/metadata.rs index e27e043..17c18eb 100644 --- a/protocol/src/types/metadata.rs +++ b/protocol/src/types/metadata.rs @@ -433,7 +433,7 @@ impl Metadata { impl Serializable for Metadata { fn read_from(buf: &mut R) -> Result { - let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION }; + let protocol_version = protocol::current_protocol_version(); if protocol_version >= 404 { Metadata::read_from113(buf) @@ -445,7 +445,7 @@ impl Serializable for Metadata { } fn write_to(&self, buf: &mut W) -> Result<(), protocol::Error> { - let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION }; + let protocol_version = protocol::current_protocol_version(); if protocol_version >= 404 { self.write_to113(buf)