use crate::types;
use crate::version::ProtocolVersion;
pub struct PlayPacketIds {
pub unsigned_command: i32,
pub signed_command: i32,
pub start_configuration: i32,
pub acknowledge_configuration: i32,
pub keep_alive: i32,
pub system_chat: i32,
}
impl PlayPacketIds {
#[must_use]
pub const fn for_version(version: ProtocolVersion) -> Self {
match version {
ProtocolVersion::V1_21 => Self {
unsigned_command: 0x04,
signed_command: 0x05,
start_configuration: 0x69,
acknowledge_configuration: 0x0C,
keep_alive: 0x26,
system_chat: 0x6C,
},
ProtocolVersion::V1_21_2 | ProtocolVersion::V1_21_4 => Self {
unsigned_command: 0x05,
signed_command: 0x06,
start_configuration: 0x70,
acknowledge_configuration: 0x0E,
keep_alive: 0x27,
system_chat: 0x73,
},
ProtocolVersion::V1_21_5 | ProtocolVersion::V1_21_6 | ProtocolVersion::V1_21_7 => {
Self {
unsigned_command: 0x05,
signed_command: 0x06,
start_configuration: 0x6F,
acknowledge_configuration: 0x0E,
keep_alive: 0x26,
system_chat: 0x72,
}
}
ProtocolVersion::V1_21_9 | ProtocolVersion::V1_21_11 => Self {
unsigned_command: 0x06,
signed_command: 0x07,
start_configuration: 0x74,
acknowledge_configuration: 0x0F,
keep_alive: 0x2B,
system_chat: 0x77,
},
}
}
}
pub struct ConfigPacketIds;
impl ConfigPacketIds {
pub const FINISHED_CONFIGURATION_CLIENTBOUND: i32 = 0x03;
pub const FINISHED_CONFIGURATION_SERVERBOUND: i32 = 0x03;
pub const DISCONNECT: i32 = 0x02;
}
#[must_use]
pub fn parse_command_from_unsigned(payload: &[u8]) -> Option<String> {
let mut cursor = payload;
types::read_string(&mut cursor).ok()
}
#[must_use]
pub fn parse_command_from_signed(payload: &[u8]) -> Option<String> {
parse_command_from_unsigned(payload)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_packet_ids_differ_per_version() {
let v121 = PlayPacketIds::for_version(ProtocolVersion::V1_21);
let v12111 = PlayPacketIds::for_version(ProtocolVersion::V1_21_11);
assert_ne!(v121.start_configuration, v12111.start_configuration);
assert_ne!(v121.system_chat, v12111.system_chat);
}
#[test]
fn test_1_21_6_inherits_from_1_21_5() {
let v1215 = PlayPacketIds::for_version(ProtocolVersion::V1_21_5);
let v1216 = PlayPacketIds::for_version(ProtocolVersion::V1_21_6);
assert_eq!(v1215.start_configuration, v1216.start_configuration);
assert_eq!(v1215.keep_alive, v1216.keep_alive);
assert_eq!(v1215.system_chat, v1216.system_chat);
}
#[test]
fn test_1_21_11_inherits_from_1_21_9() {
let v1219 = PlayPacketIds::for_version(ProtocolVersion::V1_21_9);
let v12111 = PlayPacketIds::for_version(ProtocolVersion::V1_21_11);
assert_eq!(v1219.unsigned_command, v12111.unsigned_command);
assert_eq!(v1219.start_configuration, v12111.start_configuration);
assert_eq!(v1219.keep_alive, v12111.keep_alive);
assert_eq!(v1219.system_chat, v12111.system_chat);
}
#[test]
fn test_parse_command_from_unsigned() {
let mut buf = Vec::new();
crate::types::write_string(&mut buf, "server lobby");
let cmd = parse_command_from_unsigned(&buf).unwrap();
assert_eq!(cmd, "server lobby");
}
#[test]
fn test_parse_command_from_signed() {
let mut buf = Vec::new();
crate::types::write_string(&mut buf, "server survival");
buf.extend_from_slice(&[0u8; 32]);
let cmd = parse_command_from_signed(&buf).unwrap();
assert_eq!(cmd, "server survival");
}
}