124 lines
4.3 KiB
Rust
124 lines
4.3 KiB
Rust
use std::io::{Write, Read};
|
|
|
|
use log::trace;
|
|
|
|
use crate::{ser::{Serializable, Deserializable}, varint::VarInt};
|
|
|
|
use super::{ServerPacket, ClientPacket, Protocol, ProtocolState, common::COMMON};
|
|
|
|
pub const NAME: &str = "1.13.2";
|
|
pub const VERSION: i32 = 404;
|
|
|
|
pub const PROTOCOL: Protocol = Protocol {
|
|
name: NAME,
|
|
version: VERSION,
|
|
encode,
|
|
decode,
|
|
};
|
|
|
|
fn encode(mut w: Box<&mut dyn Write>, state: ProtocolState, ev: ServerPacket) -> anyhow::Result<()> {
|
|
trace!("{NAME} encoding {ev:?}");
|
|
match ev {
|
|
ServerPacket::LoginSuccess { name, uuid } => {
|
|
VarInt(0x02).serialize(&mut w)?;
|
|
uuid.to_string().serialize(&mut w)?;
|
|
name.serialize(&mut w)?;
|
|
},
|
|
ServerPacket::ChatMessage(msg, _) => {
|
|
VarInt(0x0E).serialize(&mut w)?;
|
|
msg.serialize(&mut w)?;
|
|
0u8.serialize(&mut w)?; // chat
|
|
},
|
|
ServerPacket::SystemMessage(msg, overlay) => {
|
|
VarInt(0x0E).serialize(&mut w)?;
|
|
msg.serialize(&mut w)?;
|
|
if overlay { 2u8 } else { 1u8 } // system or overlay
|
|
.serialize(&mut w)?;
|
|
},
|
|
ServerPacket::PluginMessage { channel, data } => {
|
|
VarInt(0x19).serialize(&mut w)?;
|
|
channel.serialize(&mut w)?;
|
|
w.write_all(&data)?;
|
|
},
|
|
ServerPacket::PlayDisconnect(msg) => {
|
|
VarInt(0x1B).serialize(&mut w)?;
|
|
msg.serialize(&mut w)?;
|
|
},
|
|
ServerPacket::KeepAlive(data) => {
|
|
VarInt(0x21).serialize(&mut w)?;
|
|
data.serialize(&mut w)?;
|
|
},
|
|
ServerPacket::ChunkData { x, z } => {
|
|
VarInt(0x22).serialize(&mut w)?;
|
|
// chunk x
|
|
x.serialize(&mut w)?;
|
|
// chunk z
|
|
z.serialize(&mut w)?;
|
|
// full chunk
|
|
true.serialize(&mut w)?;
|
|
// bit mask
|
|
VarInt(0).serialize(&mut w)?;
|
|
// chunk data size and chunk data (biomes)
|
|
VarInt(256*4).serialize(&mut w)?;
|
|
[127i32; 256].serialize(&mut w)?;
|
|
// block entities
|
|
VarInt(0).serialize(&mut w)?;
|
|
},
|
|
ServerPacket::JoinGame { eid, gamemode, hardcode } => {
|
|
VarInt(0x25).serialize(&mut w)?;
|
|
eid.serialize(&mut w)?;
|
|
(gamemode | (hardcode as u8) << 3).serialize(&mut w)?;
|
|
1i32.serialize(&mut w)?; // end dimension
|
|
2u8.serialize(&mut w)?; // difficulty
|
|
255u8.serialize(&mut w)?; // max players
|
|
"default".serialize(&mut w)?; // level type
|
|
false.serialize(&mut w)?; // reduce debug info
|
|
}
|
|
ServerPacket::PositionAndLook { pos, look, flags } => {
|
|
VarInt(0x32).serialize(&mut w)?;
|
|
pos.serialize(&mut w)?;
|
|
look.serialize(&mut w)?;
|
|
flags.serialize(&mut w)?;
|
|
VarInt(0).serialize(&mut w)?; // teleport id
|
|
}
|
|
ServerPacket::SetDefaultSpawn { pos, angle: _ } => {
|
|
VarInt(0x49).serialize(&mut w)?;
|
|
pos.serialize(&mut w)?;
|
|
},
|
|
_ => { (COMMON.encode)(w, state, ev)?; }
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn decode(mut r: Box<&mut dyn Read>, state: ProtocolState, len: i32, id: i32) -> anyhow::Result<Option<ClientPacket>> {
|
|
trace!("{NAME} decoding {state:?} {id}");
|
|
type Ps = ProtocolState;
|
|
match (state, id) {
|
|
(Ps::Login, 0x00) => {
|
|
let name = String::deserialize(&mut r)?;
|
|
Ok(Some(ClientPacket::LoginStart { name, uuid: None }))
|
|
}
|
|
(Ps::Login, 0x01 | 0x02) => Ok(None), // unsupported
|
|
(Ps::Play, 0x02) => {
|
|
let mut msg = String::deserialize(&mut r)?;
|
|
if msg.starts_with('/') {
|
|
msg.remove(0);
|
|
Ok(Some(ClientPacket::Command(msg)))
|
|
} else {
|
|
Ok(Some(ClientPacket::ChatMessage(msg)))
|
|
}
|
|
},
|
|
(Ps::Play, 0x0A) => {
|
|
let channel = String::deserialize(&mut r)?;
|
|
let mut data = Vec::new();
|
|
r.read_to_end(&mut data)?;
|
|
Ok(Some(ClientPacket::PluginMessage { channel, data }))
|
|
}
|
|
(Ps::Play, 0x0E) => {
|
|
let data = i64::deserialize(&mut r)?;
|
|
Ok(Some(ClientPacket::KeepAlive(data)))
|
|
}
|
|
(Ps::Play, 0x10 | 0x11 | 0x12) => Ok(None), // position & rotation
|
|
_ => (COMMON.decode)(r, state, len, id)
|
|
}
|
|
}
|