diff --git a/Cargo.toml b/Cargo.toml index 0898d80..e6e2c19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rust_mc_proto" -description = "Minecraft packets protocol in pure rust" +description = "minecraft packets protocol in pure rust" repository = "https://github.com/MeexReay/rust_mc_proto" license-file = "LICENSE" diff --git a/README.md b/README.md index fb4edda..5f77156 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,63 @@ # rust_mc_proto -Minecraft packets protocol in pure rust \ No newline at end of file +minecraft packets protocol in pure rust +supports compression (`MinecraftConnection::set_compression`) + +all types of packets you can find on [wiki.vg](https://wiki.vg/) + + +## how to use it + +for reference: +```rust +pub type MCConn = MinecraftConnection; +``` + +example how to get motd +```rust +use std::net::TcpStream; +use varint_rs::VarintWriter; +use rust_mc_proto::{Packet, ProtocolError, MCConn}; + +fn send_handshake(conn: &mut MCConn, + protocol_version: u16, + server_address: &str, + server_port: u16, + next_state: u8) -> Result<(), ProtocolError> { + let mut packet = Packet::empty(0x00); + + packet.write_u16_varint(protocol_version)?; + packet.write_string(server_address.to_string())?; + packet.write_unsigned_short(server_port)?; + packet.write_u8_varint(next_state)?; + + conn.write_packet(&packet)?; + + Ok(()) +} + +fn send_status_request(conn: &mut MCConn) -> Result<(), ProtocolError> { + let packet = Packet::empty(0x00); + conn.write_packet(&packet)?; + + Ok(()) +} + +fn read_status_response(conn: &mut MCConn) -> Result { + let mut packet = conn.read_packet()?; + + packet.read_string() +} + +fn main() { + let mut conn = MCConn::connect("sloganmc.ru:25565").unwrap(); + + send_handshake(&mut conn, 765, "sloganmc.ru", 25565, 1).unwrap(); + send_status_request(&mut conn).unwrap(); + + println!("{}", read_status_response(&mut conn).unwrap()); // prints servers motd in json +} +``` + +also you can get minecraft connection from any stream: `MinecraftConnection::from_stream` + +I think this crate can be used for a server on rust idk -_- \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index eeaa318..7a8e609 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ use std::io::{Write, Read}; -use std::net::{SocketAddr, TcpStream, ToSocketAddrs}; +use std::net::{TcpStream, ToSocketAddrs}; use bytebuffer::ByteBuffer; use varint_rs::{VarintWriter, VarintReader}; use flate2::{Compress, Compression, Decompress, FlushCompress, Status, FlushDecompress}; @@ -109,15 +109,14 @@ impl Packet { } } -pub struct Connection { - pub stream: TcpStream, - pub addr: SocketAddr, +pub struct MinecraftConnection { + pub stream: T, compress: bool, compress_threashold: usize } -impl Connection { - pub fn build(addr: &str) -> Result { +impl MinecraftConnection { + pub fn connect(addr: &str) -> Result, ProtocolError> { let addr = match addr.to_socket_addrs() { Ok(mut i) => { match i.next() { Some(i) => { i }, @@ -131,16 +130,21 @@ impl Connection { Err(_) => { return Err(ProtocolError::StreamConnectError) }, }; - Ok(Connection { + Ok(MinecraftConnection { stream, - addr, compress: false, compress_threashold: 0 }) } +} - pub fn new(addr: &str) -> Connection { - Self::build(addr).unwrap() +impl MinecraftConnection { + pub fn new(stream: T) -> MinecraftConnection { + MinecraftConnection { + stream, + compress: false, + compress_threashold: 0 + } } pub fn set_compression(&mut self, threashold: usize) { @@ -240,13 +244,9 @@ impl Connection { Ok(()) } - - pub fn close(&mut self) { - self.stream.shutdown(std::net::Shutdown::Both).unwrap(); - } } -impl VarintWriter for Connection { +impl VarintWriter for MinecraftConnection { type Error = ProtocolError; fn write(&mut self, byte: u8) -> Result<(), Self::Error> { @@ -257,7 +257,7 @@ impl VarintWriter for Connection { } } -impl VarintReader for Connection { +impl VarintReader for MinecraftConnection { type Error = ProtocolError; fn read(&mut self) -> Result { @@ -302,4 +302,6 @@ fn decompress_zlib(bytes: &[u8]) -> Result, ProtocolError> { }, Err(_) => Err(ProtocolError::ZlibError) } -} \ No newline at end of file +} + +pub type MCConn = MinecraftConnection; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index eed82af..77a5946 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,37 +1,42 @@ -use rust_mc_proto::{Connection, Packet, ProtocolError}; -use varint_rs::{VarintReader, VarintWriter}; -use std::io::Write; +use std::net::TcpStream; +use varint_rs::VarintWriter; +use rust_mc_proto::{Packet, ProtocolError, MCConn}; -fn send_handshake(conn: &mut Connection, +fn send_handshake(conn: &mut MCConn, protocol_version: u16, server_address: &str, server_port: u16, next_state: u8) -> Result<(), ProtocolError> { let mut packet = Packet::empty(0x00); + packet.write_u16_varint(protocol_version)?; packet.write_string(server_address.to_string())?; packet.write_unsigned_short(server_port)?; packet.write_u8_varint(next_state)?; - packet.buffer.set_rpos(0); - packet.buffer.set_wpos(0); + conn.write_packet(&packet)?; - conn.write_packet(&packet) + Ok(()) } -fn send_status_request(conn: &mut Connection) -> Result<(), ProtocolError> { - conn.write_packet(&Packet::empty(0x00)) +fn send_status_request(conn: &mut MCConn) -> Result<(), ProtocolError> { + let packet = Packet::empty(0x00); + conn.write_packet(&packet)?; + + Ok(()) } -fn read_status_response(conn: &mut Connection) -> Result { +fn read_status_response(conn: &mut MCConn) -> Result { let mut packet = conn.read_packet()?; + packet.read_string() } fn main() { - let mut conn = Connection::new("localhost:25565"); + let mut conn = MCConn::connect("sloganmc.ru:25565").unwrap(); - send_handshake(&mut conn, 765, "localhost", 25565, 1).unwrap(); + send_handshake(&mut conn, 765, "sloganmc.ru", 25565, 1).unwrap(); send_status_request(&mut conn).unwrap(); + println!("{}", read_status_response(&mut conn).unwrap()); }