150 lines
4.0 KiB
Rust
150 lines
4.0 KiB
Rust
use uuid::Uuid;
|
|
|
|
use super::{data::PacketDecoder, NetworkState};
|
|
|
|
#[derive(Debug)]
|
|
pub struct Handshake {
|
|
pub version: i32,
|
|
pub addr: String,
|
|
pub port: u16,
|
|
pub next_state: i32,
|
|
}
|
|
|
|
impl Handshake {
|
|
pub fn decode(mut decoder: PacketDecoder) -> Self {
|
|
let version = decoder.read_varint();
|
|
let addr = decoder.read_string();
|
|
let port = decoder.read_ushort();
|
|
let next_state = decoder.read_varint();
|
|
Self { version, addr, port, next_state }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct SigData {
|
|
pub timestamp: i64,
|
|
pub pubkey: Vec<u8>,
|
|
pub sig: Vec<u8>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct LoginStart {
|
|
pub name: String,
|
|
pub uuid: Uuid,
|
|
}
|
|
|
|
impl LoginStart {
|
|
pub fn decode(mut decoder: PacketDecoder) -> Self {
|
|
let name = decoder.read_string();
|
|
let has_uuid = decoder.read_bool();
|
|
if !has_uuid {
|
|
panic!("Client didn't supply UUID");
|
|
}
|
|
let uuid = decoder.read_uuid();
|
|
Self { name, uuid }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ChatMessage {
|
|
pub message: String,
|
|
pub timestamp: i64,
|
|
}
|
|
|
|
impl ChatMessage {
|
|
pub fn decode(mut decoder: PacketDecoder) -> Self {
|
|
let message = decoder.read_string();
|
|
let timestamp = decoder.read_long();
|
|
// TODO read rest of packet
|
|
Self { message, timestamp }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct LoginPluginResponse {
|
|
pub id: i32,
|
|
pub data: Option<Vec<u8>>,
|
|
}
|
|
|
|
impl LoginPluginResponse {
|
|
pub fn decode(mut decoder: PacketDecoder) -> Self {
|
|
let id = decoder.read_varint();
|
|
let success = decoder.read_bool();
|
|
let data = if success {
|
|
Some(decoder.read_to_end().to_vec())
|
|
} else {
|
|
None
|
|
};
|
|
Self { id, data }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct SPluginMessage {
|
|
pub channel: String,
|
|
pub data: Vec<u8>,
|
|
}
|
|
|
|
impl SPluginMessage {
|
|
pub fn decode(mut decoder: PacketDecoder) -> Self {
|
|
let channel = decoder.read_string();
|
|
let data = decoder.read_to_end().to_vec();
|
|
Self { channel, data }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum ServerBoundPacket {
|
|
Unknown(i32),
|
|
Ignored(i32),
|
|
// handshake
|
|
Handshake(Handshake),
|
|
// status
|
|
StatusRequest(),
|
|
PingRequest(i64),
|
|
// login
|
|
LoginStart(LoginStart),
|
|
LoginPluginResponse(LoginPluginResponse),
|
|
// play
|
|
ChatMessage(ChatMessage),
|
|
ChatCommand(ChatMessage),
|
|
PluginMessage(SPluginMessage),
|
|
}
|
|
|
|
impl ServerBoundPacket {
|
|
pub fn decode(state: &mut NetworkState, mut decoder: PacketDecoder) -> ServerBoundPacket {
|
|
use NetworkState as NS;
|
|
match (*state, decoder.packet_id()) {
|
|
(NS::Handshake, 0x00) => {
|
|
let hs = Handshake::decode(decoder);
|
|
match hs.next_state {
|
|
1 => *state = NS::Status,
|
|
2 => *state = NS::Login,
|
|
state => panic!("invalid next state: {}", state)
|
|
}
|
|
ServerBoundPacket::Handshake(hs)
|
|
},
|
|
(NS::Status, 0x00)
|
|
=> ServerBoundPacket::StatusRequest(),
|
|
(NS::Status, 0x01)
|
|
=> ServerBoundPacket::PingRequest(decoder.read_long()),
|
|
(NS::Login, 0x00) => {
|
|
ServerBoundPacket::LoginStart(LoginStart::decode(decoder))
|
|
},
|
|
(NS::Login, 0x02) => {
|
|
let lpr = LoginPluginResponse::decode(decoder);
|
|
if lpr.id == -1 {
|
|
*state = NetworkState::Play;
|
|
}
|
|
ServerBoundPacket::LoginPluginResponse(lpr)
|
|
},
|
|
(NS::Play, 0x04) => ServerBoundPacket::ChatCommand(ChatMessage::decode(decoder)),
|
|
(NS::Play, 0x05) => ServerBoundPacket::ChatMessage(ChatMessage::decode(decoder)),
|
|
(NS::Play, 0x0C) => ServerBoundPacket::PluginMessage(SPluginMessage::decode(decoder)),
|
|
(NS::Play, id @ (0x11 | 0x13 | 0x14 | 0x15 | 0x1d)) => ServerBoundPacket::Ignored(id),
|
|
(_, id) => ServerBoundPacket::Unknown(id),
|
|
}
|
|
}
|
|
}
|
|
|