use anyhow::Result; use craftio_rs::{CraftAsyncReader, CraftAsyncWriter, CraftTokioConnection}; use mcproto_rs::protocol::HasPacketKind; use mcproto_rs::v1_19_3::{Packet761, Packet761Kind, RawPacket761}; use tokio::io::BufReader; use tokio::net::TcpStream; #[macro_export] macro_rules! await_packet { ($packet_type:ident, $conn:expr) => { assert_packet!( $packet_type, $conn.wait_for_packet(Packet761Kind::$packet_type).await? ) }; } #[macro_export] macro_rules! assert_packet { ($packet_type:ident, $obj:expr) => { if let Packet761::$packet_type(packet_data) = $obj { packet_data } else { panic!("Expected packet of type {}", stringify!($packet_type)) } }; ($packet_type:ident, $conn:expr, $errmgs:literal) => { assert_packet!( $packet_type, $conn .read_next_packet() .await? .ok_or(anyhow::anyhow!("Missing packet"))? ) }; } pub struct MinecraftClient { pub connection: CraftTokioConnection, } impl MinecraftClient { pub fn from_stream(stream: TcpStream) -> Self { let (read, write) = stream.into_split(); let bufread = BufReader::new(read); MinecraftClient { connection: CraftTokioConnection::from_async((bufread, write), mcproto_rs::protocol::PacketDirection::ServerBound), } } pub async fn read_next_packet(&mut self) -> Result> { if let Some(raw) = self.connection.read_packet_async::().await? { println!("Client -> Server: {:?}", raw); Ok(Some(raw)) } else { Ok(None) } } pub async fn send_packet(&mut self, packet: Packet761) -> Result<()> { println!("Server -> Client: {:?}", packet); self.connection.write_packet_async(packet).await?; Ok(()) } pub async fn wait_for_packet(&mut self, packet_kind: Packet761Kind) -> Result { loop { if let Some(packet) = self.read_next_packet().await? { if packet.kind() == packet_kind { return Ok(packet); } println!("Skipping packet {:?}", packet); } } } }