diff --git a/level.dat b/level.dat new file mode 100644 index 0000000..d7f1502 Binary files /dev/null and b/level.dat differ diff --git a/src/cycle.rs b/src/cycle.rs index 77096ef..5bf2647 100644 --- a/src/cycle.rs +++ b/src/cycle.rs @@ -1,5 +1,7 @@ -use tokio::{net::TcpStream, time::Sleep}; +use std::{thread::sleep, time::Duration}; + +use tokio::net::TcpStream; use crate::data::{clientbound, serverbound, AsyncReader, AsyncWriter, DataError, Packet, Reader, TextComponentBuilder, Writer}; @@ -153,6 +155,6 @@ async fn the_configuration(conn: &mut Connection) -> Result<(), PacketError> { let packet = Packet::empty(clientbound::configuration::FINISH); conn.write_packet(packet).await?; loop { - + sleep(Duration::from_secs(1)); } } \ No newline at end of file diff --git a/src/data/mod.rs b/src/data/mod.rs index 6801428..432b7f9 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -12,7 +12,6 @@ mod writer; mod packet; mod packet_id; mod component; -mod nbt; #[derive(Debug)] pub enum DataError { @@ -25,7 +24,7 @@ pub enum DataError { DeSerializationError, ZlibError, NBTError, - NBTCompoundError, + // NBTCompoundError, } pub type Buffer = Cursor>; @@ -49,5 +48,4 @@ pub use async_writer::*; pub use writer::*; pub use packet::*; pub use packet_id::{clientbound, serverbound}; -pub use component::*; -pub use nbt::*; \ No newline at end of file +pub use component::*; \ No newline at end of file diff --git a/src/data/nbt.rs b/src/data/nbt.rs deleted file mode 100644 index c248d23..0000000 --- a/src/data/nbt.rs +++ /dev/null @@ -1,154 +0,0 @@ -use std::{collections::HashMap, io::Cursor}; - -use super::{DataError, Reader}; - - - - -const TAG_END: u8 = 0; -const TAG_BYTE: u8 = 1; -const TAG_SHORT: u8 = 2; -const TAG_INT: u8 = 3; -const TAG_LONG: u8 = 4; -const TAG_FLOAT: u8 = 5; -const TAG_DOUBLE: u8 = 6; -const TAG_BYTE_ARRAY: u8 = 7; -const TAG_STRING: u8 = 8; -const TAG_LIST: u8 = 9; -const TAG_COMPOUND: u8 = 10; -const TAG_INT_ARRAY: u8 = 11; -const TAG_LONG_ARRAY: u8 = 12; - -#[derive(Debug)] -pub enum TAG { - END, - COMPOUND(HashMap), - STRING(String), - BYTE(i8), - SHORT(i16), - INT(i32), - LONG(i64), - FLOAT(f32), - DOUBLE(f64), - LIST(Vec), - BYTE_ARRAY(Vec), - INT_ARRAY(Vec), - LONG_ARRAY(Vec), -} - -#[derive(Debug)] -pub struct NBT { - pub key: Option, - pub value: TAG, -} - -impl NBT { - fn new(key: Option, value: TAG) -> Self { - Self { key, value } - } -} - -pub trait NBT_Reader { - fn _read_nbt(&mut self, root: bool, inet: bool, byte: Option) -> Result; - fn read_nbt(&mut self, inet: bool) -> Result; -} - - -impl NBT_Reader for Cursor> { - fn read_nbt(&mut self, inet: bool) -> Result { - self._read_nbt(true, inet, None) - } - - fn _read_nbt(&mut self, root: bool, inet: bool, b: Option) -> Result { - let byte = match b { Some(v) => v, None => self.read_byte()? }; - let mut key: Option; - - if byte == TAG_END { - return Ok(NBT::new(None, TAG::END)); - } - - if root & (byte != TAG_COMPOUND) { - return Err(DataError::NBTCompoundError) - } - - if root & inet { - key = None; - } else { - let size = self.read_short()? as usize; - let buf = self.read_bytes(size)?; - key = Some(String::from_utf8_lossy(&buf).to_string()); - } - - if b.is_some() { - key = None; - } - - match byte { - TAG_BYTE => { Ok(NBT::new(key, TAG::BYTE(self.read_signed_byte()?))) }, - TAG_SHORT => { Ok(NBT::new(key, TAG::SHORT(self.read_signed_short()?))) }, - TAG_INT => { Ok(NBT::new(key, TAG::INT(self.read_signed_int()?))) }, - TAG_LONG => { Ok(NBT::new(key, TAG::LONG(self.read_signed_long()?))) }, - TAG_FLOAT => { Ok(NBT::new(key, TAG::FLOAT(self.read_float()?))) }, - TAG_DOUBLE => { Ok(NBT::new(key, TAG::DOUBLE(self.read_double()?))) }, - - TAG_STRING => { - let size = self.read_short()? as usize; - let buf = self.read_bytes(size)?; - Ok(NBT::new(key, TAG::STRING(String::from_utf8_lossy(&buf).to_string()))) - }, - - TAG_BYTE_ARRAY => { - let size = self.read_signed_int()? as usize; - let buf = self.read_bytes(size)?.into_iter().map(|x| x as i8).collect(); - Ok(NBT::new(key, TAG::BYTE_ARRAY(buf))) - }, - - TAG_INT_ARRAY => { - let count = self.read_signed_int()? as usize; - let mut buf: Vec = Vec::with_capacity(count); - for _ in 0..count { - buf.push(self.read_signed_int()?); - } - Ok(NBT::new(key, TAG::INT_ARRAY(buf))) - }, - - TAG_LONG_ARRAY => { - let count = self.read_signed_int()? as usize; - let mut buf: Vec = Vec::with_capacity(count); - for _ in 0..count { - buf.push(self.read_signed_long()?); - } - Ok(NBT::new(key, TAG::LONG_ARRAY(buf))) - }, - - TAG_LIST => { - // byte = self.read_byte()?; - let mut buf: Vec = Vec::new(); - let count = self.read_signed_int()? as usize; - println!("List count: {count}"); - for _ in 0..count { - buf.push(self._read_nbt(false, inet, None)?); - } - Ok(NBT::new(key, TAG::LIST(buf))) - }, - - TAG_COMPOUND => { - // println!("COMPOUND"); - let mut map = HashMap::new(); - loop { - let nbt = self._read_nbt(false, inet, None)?; - if matches!(nbt.value, TAG::END) { break; }; - let Some(key) = nbt.key else { continue; }; - map.insert(key, nbt.value); - } - Ok(NBT::new(key, TAG::COMPOUND(map))) - } - - _ => { - // println!("o: {other}"); - Err(DataError::NBTError) - } - } - - } -} \ No newline at end of file diff --git a/src/data/reader.rs b/src/data/reader.rs index e5e25ae..8008d7a 100644 --- a/src/data/reader.rs +++ b/src/data/reader.rs @@ -73,12 +73,16 @@ pub trait Reader { Ok(self.read_short()? as i16) } - fn read_signed_int(&mut self) -> Result { - Ok(i32::from_be_bytes( + fn read_int(&mut self) -> Result { + Ok(u32::from_be_bytes( self.read_bytes(4)?.try_into().unwrap() )) } + fn read_signed_int(&mut self) -> Result { + Ok(self.read_int()? as i32) + } + fn read_long(&mut self) -> Result { Ok(u64::from_be_bytes( self.read_bytes(8)?.try_into().unwrap() diff --git a/src/data/writer.rs b/src/data/writer.rs index ba5a9ee..10a2b67 100644 --- a/src/data/writer.rs +++ b/src/data/writer.rs @@ -74,10 +74,12 @@ pub trait Writer { self.write_short(value as u16) } - fn write_string(&mut self, value: &str) -> Result<(), DataError> { - self.write_varint(value.len() as i32)?; - self.write_bytes(value.as_bytes())?; - Ok(()) + fn write_int(&mut self, value: u32) -> Result<(), DataError> { + self.write_bytes(&value.to_be_bytes()) + } + + fn write_signed_int(&mut self, value: i32) -> Result<(), DataError> { + self.write_int(value as u32) } fn write_long(&mut self, value: u64) -> Result<(), DataError> { @@ -88,6 +90,20 @@ pub trait Writer { self.write_long(value as u64) } + fn write_float(&mut self, value: f32) -> Result<(), DataError> { + self.write_bytes(&value.to_be_bytes()) + } + + fn write_double(&mut self, value: f64) -> Result<(), DataError> { + self.write_bytes(&value.to_be_bytes()) + } + + fn write_string(&mut self, value: &str) -> Result<(), DataError> { + self.write_varint(value.len() as i32)?; + self.write_bytes(value.as_bytes())?; + Ok(()) + } + fn write_uuid(&mut self, value: u128) -> Result<(), DataError> { self.write_bytes(&value.to_be_bytes()) } diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..aa86303 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,4 @@ +pub mod inet; +pub mod data; +pub mod cycle; +pub mod nbt; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index f01b6d6..a3786f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,41 +1,16 @@ +use rust_mc_serv::{cycle, inet::Server}; -use std::fs; - -use data::{Buffer, NBT_Reader, Reader}; -use inet::Server; - -mod data; -mod inet; -mod cycle; - #[tokio::main] async fn main() { - // let Ok(server) = Server::new("127.0.0.1:25565").await else { - // println!("Не удалось забиндить сервер"); - // return; - // }; + let Ok(server) = Server::new("127.0.0.1:25565").await else { + println!("Не удалось забиндить сервер"); + return; + }; - // loop { - // let stream = server.accept().await; - // tokio::spawn(cycle::main(stream)); - // } - - let mut buf = Buffer::new(fs::read("servers.dat").unwrap()); - - // let mut buf = Buffer::new(vec![ - // 0x0a, - // // 0x00, 0x0b, - // // 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, - // 0x08, - // 0x00, 0x04, - // 0x6e, 0x61, 0x6d, 0x65, - // 0x00, 0x05, - // 0x42, 0x61, 0x6e, 0x61, 0x6e, - // 0x00 - // ]); - - let nbt = buf.read_nbt(false).unwrap(); - println!("{nbt:?}"); + loop { + let stream = server.accept().await; + tokio::spawn(cycle::main(stream)); + } } diff --git a/src/nbt/mod.rs b/src/nbt/mod.rs new file mode 100644 index 0000000..3fe33fc --- /dev/null +++ b/src/nbt/mod.rs @@ -0,0 +1,25 @@ +pub mod reader; +pub mod writer; +mod tags; + +use std::collections::HashMap; + +pub use reader::*; +pub use writer::*; + +#[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), + LongArray(Vec), +} \ No newline at end of file diff --git a/src/nbt/reader.rs b/src/nbt/reader.rs new file mode 100644 index 0000000..8044885 --- /dev/null +++ b/src/nbt/reader.rs @@ -0,0 +1,98 @@ +use std::{collections::HashMap, io::Seek}; + +use crate::data::{Buffer, DataError, Reader}; + +use super::{tags::*, Tag}; + +trait NbtReaderInternal { + fn read_value(&mut self, t: u8) -> Result; + fn read_compound(&mut self) -> Result; + fn read_list(&mut self) -> Result; +} + +impl NbtReaderInternal for Buffer { + fn read_value(&mut self, t: u8) -> Result { + match t { + TAG_END => { self.read_byte()?; Ok(Tag::End) } + TAG_BYTE => { Ok(Tag::Byte(self.read_signed_byte()?)) } + TAG_SHORT => { Ok(Tag::Short(self.read_signed_short()?)) } + TAG_INT => { Ok(Tag::Int(self.read_signed_int()?)) } + TAG_LONG => { Ok(Tag::Long(self.read_signed_long()?)) } + TAG_FLOAT => { Ok(Tag::Float(self.read_float()?)) } + TAG_DOUBLE => { Ok(Tag::Double(self.read_double()?)) } + TAG_BYTE_ARRAY => { + let size = self.read_int()? as usize; + Ok(Tag::ByteArray(self.read_bytes(size)?.into_iter().map(|x| x as i8).collect())) + } + TAG_STRING => { + let size = self.read_short()? as usize; + let data = self.read_bytes(size)?; + Ok(Tag::String(String::from_utf8_lossy(&data).to_string())) + } + TAG_LIST => { self.read_list() } + TAG_COMPOUND => { self.read_compound() } + TAG_INT_ARRAY => { + let size = self.read_int()? as usize; + let mut data = Vec::new(); + for _ in 0..size { + data.push(self.read_signed_int()?); + } + Ok(Tag::IntArray(data)) + } + TAG_LONG_ARRAY => { + let size = self.read_int()? as usize; + let mut data = Vec::new(); + for _ in 0..size { + data.push(self.read_signed_long()?); + } + Ok(Tag::LongArray(data)) + } + other => { + println!("Неверный тэг: {other}"); + Err(DataError::NBTError) + } + } + } + + fn read_compound(&mut self) -> Result { + let mut map = HashMap::new(); + loop { + let type_of_value = self.read_byte()?; + if type_of_value == TAG_END { break; } + let size = self.read_short()? as usize; + let key = String::from_utf8_lossy(&self.read_bytes(size)?).to_string(); + map.insert(key, self.read_value(type_of_value)?); + } + Ok(Tag::Compound(map)) + } + + fn read_list(&mut self) -> Result { + let type_of_list = self.read_byte()?; + let size_of_list = self.read_signed_int()?; + let mut list = Vec::new(); + if size_of_list <= 0 { return Ok(Tag::List(list)); }; + for _ in 0..size_of_list { + list.push(self.read_value(type_of_list)?); + } + Ok(Tag::List(list)) + } +} + +pub trait NbtReader { + fn read_nbt(&mut self) -> Result; +} + +impl NbtReader for Buffer { + fn read_nbt(&mut self) -> Result { + + if self.read_byte()? != TAG_COMPOUND { + return Err(DataError::NBTError); + } + + if self.read_short()? != 0 { + let _ = self.seek_relative(-2); + } + + self.read_compound() + } +} \ No newline at end of file diff --git a/src/nbt/tags.rs b/src/nbt/tags.rs new file mode 100644 index 0000000..0170f9b --- /dev/null +++ b/src/nbt/tags.rs @@ -0,0 +1,16 @@ + + + +pub const TAG_END: u8 = 0; +pub const TAG_BYTE: u8 = 1; +pub const TAG_SHORT: u8 = 2; +pub const TAG_INT: u8 = 3; +pub const TAG_LONG: u8 = 4; +pub const TAG_FLOAT: u8 = 5; +pub const TAG_DOUBLE: u8 = 6; +pub const TAG_BYTE_ARRAY: u8 = 7; +pub const TAG_STRING: u8 = 8; +pub const TAG_LIST: u8 = 9; +pub const TAG_COMPOUND: u8 = 10; +pub const TAG_INT_ARRAY: u8 = 11; +pub const TAG_LONG_ARRAY: u8 = 12; \ No newline at end of file diff --git a/src/nbt/writer.rs b/src/nbt/writer.rs new file mode 100644 index 0000000..d032e23 --- /dev/null +++ b/src/nbt/writer.rs @@ -0,0 +1,109 @@ +use std::collections::HashMap; + +use crate::data::{Buffer, DataError, Writer}; + +use super::{tags::*, Tag}; + + + +fn get_id(tag: &Tag) -> u8 { + match tag { + Tag::End => TAG_END, + Tag::Byte(_) => TAG_BYTE, + Tag::Short(_) => TAG_SHORT, + Tag::Int(_) => TAG_INT, + Tag::Long(_) => TAG_LONG, + Tag::Float(_) => TAG_FLOAT, + Tag::Double(_) => TAG_DOUBLE, + Tag::ByteArray(_) => TAG_BYTE_ARRAY, + Tag::String(_) => TAG_STRING, + Tag::List(_) => TAG_LIST, + Tag::Compound(_) => TAG_COMPOUND, + Tag::IntArray(_) => TAG_INT_ARRAY, + Tag::LongArray(_) => TAG_LONG_ARRAY, + } +} + +trait NbtWriterInternal { + fn write_value(&mut self, tag: Tag) -> Result<(), DataError>; + fn write_compound(&mut self, map: HashMap) -> Result<(), DataError>; + fn write_list(&mut self, list: Vec) -> Result<(), DataError>; +} + +impl NbtWriterInternal for Buffer { + fn write_value(&mut self, tag: Tag) -> Result<(), DataError> { + match tag { + Tag::End => self.write_byte(0)?, + Tag::Byte(value) => self.write_signed_byte(value)?, + Tag::Short(value) => self.write_signed_short(value)?, + Tag::Int(value) => self.write_signed_int(value)?, + Tag::Long(value) => self.write_signed_long(value)?, + Tag::Float(value) => self.write_float(value)?, + Tag::Double(value) => self.write_double(value)?, + Tag::ByteArray(value) => { + self.write_int(value.len() as u32)?; + let data: Vec = value.into_iter().map(|x| x as u8).collect(); + self.write_bytes(&data)?; + } + Tag::String(value) => { + self.write_short(value.len() as u16)?; + self.write_bytes(value.as_bytes())?; + } + Tag::List(list) => self.write_list(list)?, + Tag::Compound(map) => self.write_compound(map)?, + Tag::IntArray(list) => { + self.write_int(list.len() as u32)?; + for value in list { + self.write_signed_int(value)?; + } + } + Tag::LongArray(list) => { + self.write_int(list.len() as u32)?; + for value in list { + self.write_signed_long(value)?; + } + } + } + Ok(()) + } + + fn write_compound(&mut self, map: HashMap) -> Result<(), DataError> { + for (key, tag) in map { + self.write_byte(get_id(&tag))?; + self.write_short(key.len() as u16)?; + self.write_bytes(key.as_bytes())?; + self.write_value(tag)?; + } + Ok(()) + } + + fn write_list(&mut self, list: Vec) -> Result<(), DataError> { + let type_of_list = match list.as_slice() { + [] => 0, [first, rest @ ..] => { + let first_id = get_id(first); + if rest.iter().all(|tag| get_id(tag) == first_id) { first_id } + else { return Err(DataError::NBTError) } + } + }; + self.write_byte(type_of_list)?; + self.write_int(list.len() as u32)?; + for tag in list { + self.write_value(tag)?; + } + Ok(()) + } +} + +pub trait NbtWriter { + fn write_nbt(&mut self, tag: Tag, to_file: bool) -> Result<(), DataError>; +} + +impl NbtWriter for Buffer { + fn write_nbt(&mut self, tag: Tag, to_file: bool) -> Result<(), DataError> { + let Tag::Compound(map) = tag else { return Err(DataError::NBTError); }; + self.write_byte(TAG_COMPOUND)?; + if to_file { self.write_short(0)? }; + self.write_compound(map)?; + Ok(()) + } +} \ No newline at end of file