diff options
| author | mat <github@matdoes.dev> | 2021-12-26 14:15:06 -0600 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2021-12-26 14:15:06 -0600 |
| commit | af28b0e57aeeca8790e3014f3e568c60ae892e39 (patch) | |
| tree | 497fa95e62393111f0b87d31926066153679bb52 /azalea-protocol | |
| parent | 1cdd061a999bfa16907ebcc5ab38b1863839b5f1 (diff) | |
| download | azalea-drasl-af28b0e57aeeca8790e3014f3e568c60ae892e39.tar.xz | |
reading nbt in the protocol works
Diffstat (limited to 'azalea-protocol')
| -rw-r--r-- | azalea-protocol/src/mc_buf.rs | 92 | ||||
| -rw-r--r-- | azalea-protocol/src/packets/game/clientbound_login_packet.rs | 77 | ||||
| -rw-r--r-- | azalea-protocol/src/packets/game/mod.rs | 19 | ||||
| -rw-r--r-- | azalea-protocol/src/packets/login/mod.rs | 4 |
4 files changed, 167 insertions, 25 deletions
diff --git a/azalea-protocol/src/mc_buf.rs b/azalea-protocol/src/mc_buf.rs index cf98aca3..04857235 100644 --- a/azalea-protocol/src/mc_buf.rs +++ b/azalea-protocol/src/mc_buf.rs @@ -3,6 +3,7 @@ use std::io::Write; use async_trait::async_trait; +use azalea_core::resource_location::ResourceLocation; use byteorder::{BigEndian, WriteBytesExt}; use tokio::io::{AsyncRead, AsyncReadExt}; @@ -39,6 +40,11 @@ pub trait Writable { fn write_int(&mut self, n: i32) -> Result<(), std::io::Error>; fn write_boolean(&mut self, b: bool) -> Result<(), std::io::Error>; fn write_nbt(&mut self, nbt: &azalea_nbt::Tag) -> Result<(), std::io::Error>; + fn write_long(&mut self, n: i64) -> Result<(), std::io::Error>; + fn write_resource_location( + &mut self, + location: &ResourceLocation, + ) -> Result<(), std::io::Error>; } #[async_trait] @@ -140,6 +146,17 @@ impl Writable for Vec<u8> { nbt.write(self) .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) } + + fn write_long(&mut self, n: i64) -> Result<(), std::io::Error> { + WriteBytesExt::write_i64::<BigEndian>(self, n) + } + + fn write_resource_location( + &mut self, + location: &ResourceLocation, + ) -> Result<(), std::io::Error> { + self.write_utf(&location.to_string()) + } } #[async_trait] @@ -156,6 +173,8 @@ pub trait Readable { async fn read_int(&mut self) -> Result<i32, String>; async fn read_boolean(&mut self) -> Result<bool, String>; async fn read_nbt(&mut self) -> Result<azalea_nbt::Tag, String>; + async fn read_long(&mut self) -> Result<i64, String>; + async fn read_resource_location(&mut self) -> Result<ResourceLocation, String>; } #[async_trait] @@ -285,14 +304,32 @@ where } async fn read_nbt(&mut self) -> Result<azalea_nbt::Tag, String> { - Ok(azalea_nbt::Tag::read(self).await.unwrap()) + match azalea_nbt::Tag::read(self).await { + Ok(r) => Ok(r), + // Err(e) => Err(e.to_string()), + Err(e) => Err(e.to_string()).unwrap(), + } + } + + async fn read_long(&mut self) -> Result<i64, String> { + match AsyncReadExt::read_i64(self).await { + Ok(r) => Ok(r), + Err(_) => Err("Error reading long".to_string()), + } + } + + async fn read_resource_location(&mut self) -> Result<ResourceLocation, String> { + // get the resource location from the string + let location_string = self.read_utf().await?; + let location = ResourceLocation::new(&location_string)?; + Ok(location) } } #[cfg(test)] mod tests { use super::*; - use std::io::Cursor; + use std::{collections::HashMap, io::Cursor}; use tokio::io::BufReader; #[test] @@ -387,4 +424,55 @@ mod tests { ] ); } + + #[tokio::test] + async fn test_nbt() { + let mut buf = Vec::new(); + buf.write_nbt(&azalea_nbt::Tag::Compound(HashMap::from_iter(vec![( + "hello world".to_string(), + azalea_nbt::Tag::Compound(HashMap::from_iter(vec![( + "name".to_string(), + azalea_nbt::Tag::String("Bananrama".to_string()), + )])), + )]))) + .unwrap(); + + let mut buf = BufReader::new(Cursor::new(buf)); + + let result = buf.read_nbt().await.unwrap(); + assert_eq!( + result, + azalea_nbt::Tag::Compound(HashMap::from_iter(vec![( + "hello world".to_string(), + azalea_nbt::Tag::Compound(HashMap::from_iter(vec![( + "name".to_string(), + azalea_nbt::Tag::String("Bananrama".to_string()), + )])), + )])) + ); + } + + #[tokio::test] + async fn test_long() { + let mut buf = Vec::new(); + buf.write_long(123456).unwrap(); + + let mut buf = BufReader::new(Cursor::new(buf)); + + assert_eq!(buf.read_long().await.unwrap(), 123456); + } + + #[tokio::test] + async fn test_resource_location() { + let mut buf = Vec::new(); + buf.write_resource_location(&ResourceLocation::new("minecraft:dirt").unwrap()) + .unwrap(); + + let mut buf = BufReader::new(Cursor::new(buf)); + + assert_eq!( + buf.read_resource_location().await.unwrap(), + ResourceLocation::new("minecraft:dirt").unwrap() + ); + } } diff --git a/azalea-protocol/src/packets/game/clientbound_login_packet.rs b/azalea-protocol/src/packets/game/clientbound_login_packet.rs index 54205c48..1b90ce14 100644 --- a/azalea-protocol/src/packets/game/clientbound_login_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_login_packet.rs @@ -1,6 +1,7 @@ use super::GamePacket; use crate::mc_buf::{Readable, Writable}; use azalea_core::{game_type::GameType, resource_location::ResourceLocation}; +use tokio::io::AsyncReadExt; #[derive(Clone, Debug)] pub struct ClientboundLoginPacket { @@ -50,27 +51,73 @@ impl ClientboundLoginPacket { buf.write_byte(self.game_type.to_id())?; buf.write_byte(GameType::to_optional_id(&self.previous_game_type) as u8)?; buf.write_list(&self.levels, |buf, resource_location| { - buf.write_utf(&resource_location.to_string()) + buf.write_resource_location(resource_location) })?; - self.registry_holder - .write(buf) - .map_err(|_| std::io::Error::new(std::io::ErrorKind::Other, "write registry holder"))?; - + buf.write_nbt(&self.registry_holder)?; + buf.write_nbt(&self.dimension_type)?; + buf.write_resource_location(&self.dimension)?; + buf.write_long(self.seed)?; + buf.write_varint(self.max_players)?; + buf.write_varint(self.chunk_radius)?; + buf.write_varint(self.simulation_distance)?; + buf.write_boolean(self.reduced_debug_info)?; + buf.write_boolean(self.show_death_screen)?; + buf.write_boolean(self.is_debug)?; + buf.write_boolean(self.is_flat)?; Ok(()) } pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>( buf: &mut T, ) -> Result<GamePacket, String> { - let transaction_id = buf.read_varint().await? as u32; - let identifier = ResourceLocation::new(&buf.read_utf().await?)?; - let data = buf.read_bytes(1048576).await?; - panic!("not implemented"); - // Ok(ClientboundLoginPacket { - // transaction_id, - // identifier, - // data, - // } - // .get()) + let player_id = buf.read_int().await?; + let hardcore = buf.read_boolean().await?; + let game_type = GameType::from_id(buf.read_byte().await?)?; + let previous_game_type = GameType::from_optional_id(buf.read_byte().await? as i8)?; + + let mut levels = Vec::new(); + let length = buf.read_varint().await?; + for _ in 0..length { + levels.push(buf.read_resource_location().await?); + } + + // println!("about to read nbt"); + // // read all the bytes into a buffer, print it, and panic + // let mut registry_holder_buf = Vec::new(); + // buf.read_to_end(&mut registry_holder_buf).await.unwrap(); + // println!("{:?}", String::from_utf8_lossy(®istry_holder_buf)); + // panic!(""); + + let registry_holder = buf.read_nbt().await?; + let dimension_type = buf.read_nbt().await?; + let dimension = buf.read_resource_location().await?; + let seed = buf.read_long().await?; + let max_players = buf.read_varint().await?; + let chunk_radius = buf.read_varint().await?; + let simulation_distance = buf.read_varint().await?; + let reduced_debug_info = buf.read_boolean().await?; + let show_death_screen = buf.read_boolean().await?; + let is_debug = buf.read_boolean().await?; + let is_flat = buf.read_boolean().await?; + + Ok(ClientboundLoginPacket { + player_id, + hardcore, + game_type, + previous_game_type, + levels, + registry_holder, + dimension_type, + dimension, + seed, + max_players, + chunk_radius, + simulation_distance, + reduced_debug_info, + show_death_screen, + is_debug, + is_flat, + } + .get()) } } diff --git a/azalea-protocol/src/packets/game/mod.rs b/azalea-protocol/src/packets/game/mod.rs index 932435d9..5697a0ad 100644 --- a/azalea-protocol/src/packets/game/mod.rs +++ b/azalea-protocol/src/packets/game/mod.rs @@ -25,16 +25,23 @@ impl ProtocolPacket for GamePacket { /// Read a packet by its id, ConnectionProtocol, and flow async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>( - _id: u32, + id: u32, flow: &PacketFlow, - _buf: &mut T, + buf: &mut T, ) -> Result<GamePacket, String> where Self: Sized, { - match flow { - PacketFlow::ServerToClient => Err("HandshakePacket::read not implemented".to_string()), - PacketFlow::ClientToServer => Err("HandshakePacket::read not implemented".to_string()), - } + Ok(match flow { + PacketFlow::ServerToClient => match id { + 0x26 => clientbound_login_packet::ClientboundLoginPacket::read(buf).await?, + + _ => return Err(format!("Unknown ServerToClient game packet id: {}", id)), + }, + PacketFlow::ClientToServer => match id { + // 0x00 => serverbound_hello_packet::ServerboundHelloPacket::read(buf).await?, + _ => return Err(format!("Unknown ClientToServer game packet id: {}", id)), + }, + }) } } diff --git a/azalea-protocol/src/packets/login/mod.rs b/azalea-protocol/src/packets/login/mod.rs index 65d94bed..4d490d08 100644 --- a/azalea-protocol/src/packets/login/mod.rs +++ b/azalea-protocol/src/packets/login/mod.rs @@ -68,11 +68,11 @@ impl ProtocolPacket for LoginPacket { ) .await? } - _ => return Err(format!("Unknown ServerToClient status packet id: {}", id)), + _ => return Err(format!("Unknown ServerToClient login packet id: {}", id)), }, PacketFlow::ClientToServer => match id { 0x00 => serverbound_hello_packet::ServerboundHelloPacket::read(buf).await?, - _ => return Err(format!("Unknown ClientToServer status packet id: {}", id)), + _ => return Err(format!("Unknown ClientToServer login packet id: {}", id)), }, }) } |
