Compare commits

...

4 Commits

Author SHA1 Message Date
GIKExe
52ed60c758 nbt 95% 2025-05-19 06:59:47 +03:00
GIKExe
07b7fd4cdf nbt -100% 2025-05-16 12:02:15 +03:00
GIKExe
3e5fb4f149 nbt 90% 2025-05-16 10:05:00 +03:00
GIKExe
020b9a1d78 nbt? 2025-05-16 07:43:46 +03:00
14 changed files with 312 additions and 106 deletions

BIN
level.dat Normal file

Binary file not shown.

BIN
servers.dat Normal file

Binary file not shown.

View File

@ -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));
}
}

View File

@ -32,10 +32,6 @@ pub trait AsyncReader {
Ok(self.read_bytes(1).await?[0])
}
async fn read_signed_byte(&mut self) -> Result<i8, DataError> {
Ok(self.read_byte().await? as i8)
}
async fn read_varint_size(&mut self) -> Result<(i32, usize), DataError> {
let mut value = 0;
let mut position = 0;
@ -71,36 +67,4 @@ pub trait AsyncReader {
let id = cursor.read_varint()?;
Ok(Packet::new(id as u8, cursor))
}
async fn read_short(&mut self) -> Result<u16, DataError> {
Ok(u16::from_be_bytes(
self.read_bytes(2).await?.try_into().unwrap()
))
}
async fn read_signed_short(&mut self) -> Result<i16, DataError> {
Ok(self.read_short().await? as i16)
}
async fn read_string(&mut self) -> Result<String, DataError> {
let size = self.read_varint().await?;
let vec = self.read_bytes(size as usize).await?;
String::from_utf8(vec).or( Err(DataError::StringDecodeError))
}
async fn read_long(&mut self) -> Result<u64, DataError> {
Ok(u64::from_be_bytes(
self.read_bytes(8).await?.try_into().unwrap()
))
}
async fn read_signed_long(&mut self) -> Result<i64, DataError> {
Ok(self.read_long().await? as i64)
}
async fn read_uuid(&mut self) -> Result<u128, DataError> {
Ok(u128::from_be_bytes(
self.read_bytes(16).await?.try_into().unwrap()
))
}
}

View File

@ -15,30 +15,6 @@ impl AsyncWriter for TcpStream {
pub trait AsyncWriter {
async fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), DataError>;
async fn write_byte(&mut self, value: u8) -> Result<(), DataError> {
self.write_bytes(&[value]).await
}
async fn write_signed_byte(&mut self, value: i8) -> Result<(), DataError> {
self.write_byte(value as u8).await
}
async fn write_varint_size(&mut self, value: i32) -> Result<usize, DataError> {
let mut _value = value as u32;
let mut position = 0;
loop {
let mut byte = (_value & 127) as u8;
position += 1; _value >>= 7;
if _value != 0 { byte += 128; };
self.write_byte(byte).await?;
if _value == 0 { return Ok(position) }
}
}
async fn write_varint(&mut self, value: i32) -> Result<(), DataError> {
self.write_varint_size(value).await?; Ok(())
}
async fn write_packet(&mut self, packet: Packet, threshold: Option<usize>)
-> Result<(), DataError> {
let mut buf = Vec::new();
@ -67,30 +43,4 @@ pub trait AsyncWriter {
self.write_bytes(&buf).await?;
Ok(())
}
async fn write_short(&mut self, value: u16) -> Result<(), DataError> {
self.write_bytes(&value.to_be_bytes()).await
}
async fn write_signed_short(&mut self, value: i16) -> Result<(), DataError> {
self.write_short(value as u16).await
}
async fn write_string(&mut self, value: &str) -> Result<(), DataError> {
self.write_varint(value.len() as i32).await?;
self.write_bytes(value.as_bytes()).await?;
Ok(())
}
async fn write_long(&mut self, value: u64) -> Result<(), DataError> {
self.write_bytes(&value.to_be_bytes()).await
}
async fn write_signed_long(&mut self, value: i64) -> Result<(), DataError> {
self.write_long(value as u64).await
}
async fn write_uuid(&mut self, value: u128) -> Result<(), DataError> {
self.write_bytes(&value.to_be_bytes()).await
}
}

View File

@ -1,4 +1,4 @@
use std::io::{Read, Write};
use std::io::{Cursor, Read, Write};
use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression};
@ -23,8 +23,12 @@ pub enum DataError {
SerializationError,
DeSerializationError,
ZlibError,
NBTError,
// NBTCompoundError,
}
pub type Buffer = Cursor<Vec<u8>>;
pub fn decompress(bytes: &[u8]) -> Result<Vec<u8>, DataError> {
let mut decoder = ZlibDecoder::new(bytes);
let mut output = Vec::new();

View File

@ -1,11 +1,13 @@
use std::io::{Cursor, Read};
use super::{decompress, DataError, Packet};
use super::{decompress, Buffer, DataError, Packet};
impl<R: Read> Reader for R {
impl Reader for Buffer {
fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError> {
println!("Read bytes: {size}");
if size == 0 { return Ok(Vec::new());};
let mut buf = vec![0; size];
match self.read_exact(&mut buf) {
Ok(_) => Ok(buf),
@ -71,10 +73,14 @@ pub trait Reader {
Ok(self.read_short()? as i16)
}
fn read_string(&mut self) -> Result<String, DataError> {
let size = self.read_varint()?;
let vec = self.read_bytes(size as usize)?;
String::from_utf8(vec).or( Err(DataError::StringDecodeError))
fn read_int(&mut self) -> Result<u32, DataError> {
Ok(u32::from_be_bytes(
self.read_bytes(4)?.try_into().unwrap()
))
}
fn read_signed_int(&mut self) -> Result<i32, DataError> {
Ok(self.read_int()? as i32)
}
fn read_long(&mut self) -> Result<u64, DataError> {
@ -87,6 +93,24 @@ pub trait Reader {
Ok(self.read_long()? as i64)
}
fn read_float(&mut self) -> Result<f32, DataError> {
Ok(f32::from_be_bytes(
self.read_bytes(4)?.try_into().unwrap()
))
}
fn read_double(&mut self) -> Result<f64, DataError> {
Ok(f64::from_be_bytes(
self.read_bytes(8)?.try_into().unwrap()
))
}
fn read_string(&mut self) -> Result<String, DataError> {
let size = self.read_varint()?;
let vec = self.read_bytes(size as usize)?;
String::from_utf8(vec).or( Err(DataError::StringDecodeError))
}
fn read_uuid(&mut self) -> Result<u128, DataError> {
Ok(u128::from_be_bytes(
self.read_bytes(16)?.try_into().unwrap()

View File

@ -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())
}

4
src/lib.rs Normal file
View File

@ -0,0 +1,4 @@
pub mod inet;
pub mod data;
pub mod cycle;
pub mod nbt;

View File

@ -1,12 +1,6 @@
use rust_mc_serv::{cycle, inet::Server};
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 {

25
src/nbt/mod.rs Normal file
View File

@ -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<i8>),
String(String),
List(Vec<Tag>),
Compound(HashMap<String, Tag>),
IntArray(Vec<i32>),
LongArray(Vec<i64>),
}

98
src/nbt/reader.rs Normal file
View File

@ -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<Tag, DataError>;
fn read_compound(&mut self) -> Result<Tag, DataError>;
fn read_list(&mut self) -> Result<Tag, DataError>;
}
impl NbtReaderInternal for Buffer {
fn read_value(&mut self, t: u8) -> Result<Tag, DataError> {
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<Tag, DataError> {
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<Tag, DataError> {
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<Tag, DataError>;
}
impl NbtReader for Buffer {
fn read_nbt(&mut self) -> Result<Tag, DataError> {
if self.read_byte()? != TAG_COMPOUND {
return Err(DataError::NBTError);
}
if self.read_short()? != 0 {
let _ = self.seek_relative(-2);
}
self.read_compound()
}
}

16
src/nbt/tags.rs Normal file
View File

@ -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;

109
src/nbt/writer.rs Normal file
View File

@ -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<String, Tag>) -> Result<(), DataError>;
fn write_list(&mut self, list: Vec<Tag>) -> 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<u8> = 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<String, Tag>) -> 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<Tag>) -> 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(())
}
}