use std::time::Duration;
use anyhow::Context;
use tokio::time::sleep;
use crate::mc_text::ServerStatus;
use crate::varint::VarInt;
#[derive(Debug)]
pub struct ClientHandshake {
pub len: VarInt,
pub packet_id: VarInt,
pub protocol_version: VarInt,
pub server_addr: String,
pub server_port: u16,
pub next_state: VarInt,
}
impl ClientHandshake {
pub fn new(server_addr: String, server_port: u16) -> ClientHandshake {
let packet_id = VarInt::from(0x00);
let protocol_version = VarInt::from(768);
let next_state = VarInt::from(1);
let len_val =
packet_id.size() +
protocol_version.size() +
VarInt::from(server_addr.len() as i32).size() +
server_addr.len() +
2 + next_state.size();
let len = VarInt::from(len_val as i32);
let handshake = ClientHandshake {
len,
packet_id,
protocol_version,
server_addr,
server_port,
next_state,
};
handshake
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut buf = Vec::new();
fn write_varint_bytes(buf: &mut Vec<u8>, varint_inner: &[u8]) {
for &byte in varint_inner {
buf.push(byte);
if byte & 0b1000_0000 == 0 {
break;
}
}
}
write_varint_bytes(&mut buf, &self.len.inner);
write_varint_bytes(&mut buf, &self.packet_id.inner);
write_varint_bytes(&mut buf, &self.protocol_version.inner);
let addr_len = VarInt::from(self.server_addr.len() as i32);
write_varint_bytes(&mut buf, &addr_len.inner);
buf.extend(self.server_addr.as_bytes());
buf.push((self.server_port >> 8) as u8);
buf.push(self.server_port as u8);
write_varint_bytes(&mut buf, &self.next_state.inner);
buf
}
}
pub struct StatusQuery {
len: VarInt,
packet_id: VarInt,
}
impl StatusQuery {
pub fn new() -> StatusQuery {
let packet_id = VarInt::from(0x00);
let len = VarInt::from(1); StatusQuery {
len,
packet_id,
}
}
pub fn to_bytes(&self) -> Vec<u8> {
vec![0x01, 0x00]
}
}
#[derive(Debug)]
pub struct ServerQueryResponse {
pub len: VarInt,
pub packet_id: VarInt,
pub json_len: VarInt,
pub json: String,
}
impl ServerQueryResponse {
pub async fn from(bytes: &[u8]) -> ServerQueryResponse {
sleep(Duration::from_millis(100)).await; fn read_varint(data: &[u8]) -> (VarInt, usize) {
let mut val = VarInt::default();
let mut i = 0;
loop {
let byte = data[i];
val.inner[i] = byte;
i += 1;
if byte & 0x80 == 0 {
break;
}
}
(val, i)
}
let mut cursor = 0;
let (len, len_size) = read_varint(&bytes[cursor..]);
cursor += len_size;
let (packet_id, packet_id_size) = read_varint(&bytes[cursor..]);
cursor += packet_id_size;
let (json_len, json_len_size) = read_varint(&bytes[cursor..]);
cursor += json_len_size;
let json_bytes = &bytes[cursor..cursor + i32::from(json_len.clone()) as usize];
cursor += i32::from(json_len.clone()) as usize;
let json = String::from_utf8_lossy(json_bytes).to_string();
ServerQueryResponse {
len,
packet_id,
json_len,
json,
}
}
pub fn parse_status(&self) -> anyhow::Result<ServerStatus> {
let status: ServerStatus = serde_json::from_str(&self.json)
.context("Failed to deserialize ServerQueryResponse.json into ServerStatus")?;
Ok(status)
}
}