217 lines
5.9 KiB
Rust

use crate::data::server_status::*;
use crate::decoder::Decoder;
use crate::error::DecodeError;
use crate::{trait_packet_id, version::PacketId};
use minecraft_protocol_derive::{Decoder, Encoder};
use std::io::Read;
pub enum StatusServerBoundPacket {
StatusRequest(StatusRequest),
PingRequest(PingRequest),
}
pub enum StatusClientBoundPacket {
StatusResponse(StatusResponse),
PingResponse(PingResponse),
}
impl StatusServerBoundPacket {
pub fn get_type_id(&self) -> u8 {
match self {
StatusServerBoundPacket::StatusRequest(_) => 0x00,
StatusServerBoundPacket::PingRequest(_) => 0x01,
}
}
pub fn decode<R: Read>(type_id: u8, reader: &mut R) -> Result<Self, DecodeError> {
match type_id {
0x00 => Ok(StatusServerBoundPacket::StatusRequest(StatusRequest {})),
0x01 => {
let ping_request = PingRequest::decode(reader)?;
Ok(StatusServerBoundPacket::PingRequest(ping_request))
}
_ => Err(DecodeError::UnknownPacketType { type_id }),
}
}
}
impl StatusClientBoundPacket {
pub fn get_type_id(&self) -> u8 {
match self {
StatusClientBoundPacket::StatusResponse(_) => 0x00,
StatusClientBoundPacket::PingResponse(_) => 0x01,
}
}
}
#[derive(Encoder, Decoder, Debug)]
pub struct PingRequest {
pub time: u64,
}
impl PingRequest {
pub fn new(time: u64) -> StatusServerBoundPacket {
let ping_request = PingRequest { time };
StatusServerBoundPacket::PingRequest(ping_request)
}
}
#[derive(Encoder, Decoder, Debug)]
pub struct PingResponse {
pub time: u64,
}
impl PingResponse {
pub fn new(time: u64) -> StatusClientBoundPacket {
let ping_response = PingResponse { time };
StatusClientBoundPacket::PingResponse(ping_response)
}
}
#[derive(Encoder, Decoder, Debug)]
pub struct StatusRequest {}
impl StatusRequest {
pub fn new() -> StatusServerBoundPacket {
StatusServerBoundPacket::StatusRequest(StatusRequest {})
}
}
#[derive(Encoder, Decoder, Debug)]
pub struct StatusResponse {
pub server_status: ServerStatus,
}
impl StatusResponse {
pub fn new(server_status: ServerStatus) -> StatusClientBoundPacket {
let status_response = StatusResponse { server_status };
StatusClientBoundPacket::StatusResponse(status_response)
}
}
#[cfg(test)]
mod tests {
use crate::data::chat::{Message, Payload};
use crate::decoder::Decoder;
use crate::encoder::Encoder;
use crate::version::v1_14_4::status::*;
use std::io::Cursor;
use uuid::Uuid;
#[test]
fn test_ping_request_encode() {
let ping_request = PingRequest {
time: 1577735845610,
};
let mut vec = Vec::new();
ping_request.encode(&mut vec).unwrap();
assert_eq!(
vec,
include_bytes!("../../../test/packet/status/ping_request.dat").to_vec()
);
}
#[test]
fn test_status_ping_request_decode() {
let mut cursor =
Cursor::new(include_bytes!("../../../test/packet/status/ping_request.dat").to_vec());
let ping_request = PingRequest::decode(&mut cursor).unwrap();
assert_eq!(ping_request.time, 1577735845610);
}
#[test]
fn test_ping_response_encode() {
let ping_response = PingResponse {
time: 1577735845610,
};
let mut vec = Vec::new();
ping_response.encode(&mut vec).unwrap();
assert_eq!(
vec,
include_bytes!("../../../test/packet/status/ping_response.dat").to_vec()
);
}
#[test]
fn test_status_ping_response_decode() {
let mut cursor =
Cursor::new(include_bytes!("../../../test/packet/status/ping_response.dat").to_vec());
let ping_response = PingResponse::decode(&mut cursor).unwrap();
assert_eq!(ping_response.time, 1577735845610);
}
#[test]
fn test_status_response_encode() {
let version = ServerVersion {
name: String::from("1.15.1"),
protocol: 575,
};
let player = OnlinePlayer {
id: Uuid::parse_str("2a1e1912-7103-4add-80fc-91ebc346cbce").unwrap(),
name: String::from("Username"),
};
let players = OnlinePlayers {
online: 10,
max: 100,
sample: vec![player],
};
let server_status = ServerStatus {
version,
description: Message::new(Payload::text("Description")),
players,
};
let status_response = StatusResponse { server_status };
let mut vec = Vec::new();
status_response.encode(&mut vec).unwrap();
assert_eq!(
vec,
include_bytes!("../../../test/packet/status/status_response.dat").to_vec()
);
}
#[test]
fn test_status_response_decode() {
let mut cursor =
Cursor::new(include_bytes!("../../../test/packet/status/status_response.dat").to_vec());
let status_response = StatusResponse::decode(&mut cursor).unwrap();
let server_status = status_response.server_status;
let player = OnlinePlayer {
id: Uuid::parse_str("2a1e1912-7103-4add-80fc-91ebc346cbce").unwrap(),
name: String::from("Username"),
};
assert_eq!(server_status.version.name, String::from("1.15.1"));
assert_eq!(server_status.version.protocol, 575);
assert_eq!(server_status.players.max, 100);
assert_eq!(server_status.players.online, 10);
assert_eq!(server_status.players.sample, vec![player]);
assert_eq!(
server_status.description,
Message::new(Payload::text("Description"))
);
}
}
trait_packet_id!(StatusRequest, 0x00);
trait_packet_id!(PingRequest, 0x01);
trait_packet_id!(StatusResponse, 0x00);
trait_packet_id!(PingResponse, 0x01);