quectocraft2/src/protocol/v1_13_2.rs

125 lines
4.3 KiB
Rust
Raw Normal View History

2023-08-02 00:44:57 -04:00
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)
}
}