packet id constants

This commit is contained in:
MeexReay 2025-05-03 04:19:46 +03:00
parent fbcb1ce123
commit 0c9f9dbf0c
3 changed files with 57 additions and 50 deletions

View File

@ -17,7 +17,7 @@ pub mod protocol;
// Ошибки сервера // Ошибки сервера
#[derive(Debug)] #[derive(Debug)]
pub enum ServerError { pub enum ServerError {
UnknownPacket(String), // Неизвестный пакет, в строке указана ситуация в которой он неизвестен UnexpectedPacket, // Неожиданный пакет
Protocol(ProtocolError), // Ошибка в протоколе при работе с rust_mc_proto Protocol(ProtocolError), // Ошибка в протоколе при работе с rust_mc_proto
ConnectionClosed, // Соединение закрыто, единственная ошибка которая не логируется у handle_connection ConnectionClosed, // Соединение закрыто, единственная ошибка которая не логируется у handle_connection
SerTextComponent, // Ошибка при сериализации текст-компонента SerTextComponent, // Ошибка при сериализации текст-компонента

View File

@ -107,7 +107,7 @@ impl ClientContext {
Ok(()) Ok(())
} }
pub fn read_packet(self: &Arc<Self>) -> Result<Packet, ServerError> { pub fn read_any_packet(self: &Arc<Self>) -> Result<Packet, ServerError> {
let state = self.state(); let state = self.state();
let mut conn = self.conn.read().unwrap().try_clone()?; // так можно делать т.к сокет это просто поинтер let mut conn = self.conn.read().unwrap().try_clone()?; // так можно делать т.к сокет это просто поинтер
@ -127,6 +127,15 @@ impl ClientContext {
} }
} }
pub fn read_packet(self: &Arc<Self>, id: u8) -> Result<Packet, ServerError> {
let packet = self.read_any_packet()?;
if packet.id() != id {
Err(ServerError::UnexpectedPacket)
} else {
Ok(packet)
}
}
pub fn close(self: &Arc<Self>) { pub fn close(self: &Arc<Self>) {
self.conn.write().unwrap().close(); self.conn.write().unwrap().close();
} }

View File

@ -5,6 +5,23 @@ use rust_mc_proto::{DataReader, DataWriter, Packet};
use crate::{server::data::text_component::TextComponent, trigger_event}; use crate::{server::data::text_component::TextComponent, trigger_event};
// Тут будут все айди пакетов
pub const HANDSHAKE_ID: u8 = 0x00;
pub const STATUS_REQUEST_ID: u8 = 0x00;
pub const STATUS_RESPONSE_ID: u8 = 0x00;
pub const STATUS_PING_REQUEST_ID: u8 = 0x01;
pub const STATUS_PING_RESPONSE_ID: u8 = 0x01;
pub const LOGIN_START_ID: u8 = 0x00;
pub const LOGIN_SET_COMPRESSION_ID: u8 = 0x03;
pub const LOGIN_SUCCESS_ID: u8 = 0x02;
pub const LOGIN_ACKNOWLEDGED_ID: u8 = 0x03;
pub const CONFIGURATION_SERVERBOUND_PLUGIN_MESSAGE_ID: u8 = 0x02;
pub const CONFIGURATION_CLIENT_INFORMATION_ID: u8 = 0x00;
pub const CONFIGURATION_FINISH_ID: u8 = 0x03;
pub const CONFIGURATION_ACKNOWLEDGE_FINISH_ID: u8 = 0x03;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ConnectionState { pub enum ConnectionState {
Handshake, Handshake,
@ -21,11 +38,7 @@ pub fn handle_connection(
// Получение пакетов производится через client.conn(), // Получение пакетов производится через client.conn(),
// ВАЖНО: не помещать сам client.conn() в переменные, // ВАЖНО: не помещать сам client.conn() в переменные,
// он должен сразу убиваться иначе соединение гдето задедлочится // он должен сразу убиваться иначе соединение гдето задедлочится
let mut packet = client.read_packet()?; let mut packet = client.read_packet(HANDSHAKE_ID)?;
if packet.id() != 0x00 {
return Err(ServerError::UnknownPacket(format!("Неизвестный пакет рукопожатия")));
} // Айди пакета не рукопожатное - выходим из функции
let protocol_version = packet.read_varint()?; // Получаем версия протокола, может быть отрицательным если наш клиент дэбил let protocol_version = packet.read_varint()?; // Получаем версия протокола, может быть отрицательным если наш клиент дэбил
let server_address = packet.read_string()?; // Получаем домен/адрес сервера к которому пытается подключиться клиент, например "play.example.com", а не айпи let server_address = packet.read_string()?; // Получаем домен/адрес сервера к которому пытается подключиться клиент, например "play.example.com", а не айпи
@ -40,11 +53,11 @@ pub fn handle_connection(
loop { loop {
// Чтение запроса // Чтение запроса
let packet = client.read_packet()?; let mut packet = client.read_any_packet()?;
match packet.id() { match packet.id() {
0x00 => { // Запрос статуса STATUS_REQUEST_ID => { // Запрос статуса
let mut packet = Packet::empty(0x00); let mut packet = Packet::empty(STATUS_RESPONSE_ID);
// Дефолтный статус // Дефолтный статус
let mut status = "{ let mut status = "{
@ -63,13 +76,16 @@ pub fn handle_connection(
client.write_packet(&packet)?; client.write_packet(&packet)?;
}, },
0x01 => { // Пинг STATUS_PING_REQUEST_ID => { // Пинг
// Раньше мы просто отправляли ему его-же пакет, но сейчас,
// С приходом к власти констант айди-пакетов, нам приходится делать такое непотребство
let timestamp = packet.read_long()?;
let mut packet = Packet::empty(STATUS_PING_RESPONSE_ID);
packet.write_long(timestamp)?;
client.write_packet(&packet)?; client.write_packet(&packet)?;
// Просто отправляем этот же пакет обратно
// ID такой-же, содержание тоже, так почему бы и нет?
}, },
_ => { _ => {
return Err(ServerError::UnknownPacket(format!("Неизвестный пакет при чтении запросов статуса"))); return Err(ServerError::UnexpectedPacket);
} }
} }
} }
@ -78,7 +94,7 @@ pub fn handle_connection(
client.set_state(ConnectionState::Login)?; // Мы находимся в режиме Login client.set_state(ConnectionState::Login)?; // Мы находимся в режиме Login
// Читаем пакет Login Start // Читаем пакет Login Start
let mut packet = client.read_packet()?; let mut packet = client.read_packet(LOGIN_START_ID)?;
let name = packet.read_string()?; let name = packet.read_string()?;
let uuid = packet.read_uuid()?; let uuid = packet.read_uuid()?;
@ -91,31 +107,26 @@ pub fn handle_connection(
// Отправляем пакет Set Compression если сжатие указано // Отправляем пакет Set Compression если сжатие указано
if let Some(threshold) = client.server.config.server.compression_threshold { if let Some(threshold) = client.server.config.server.compression_threshold {
client.write_packet(&Packet::build(0x03, |p| p.write_usize_varint(threshold))?)?; client.write_packet(&Packet::build(LOGIN_SET_COMPRESSION_ID, |p| p.write_usize_varint(threshold))?)?;
client.set_compression(Some(threshold)); // Устанавливаем сжатие на соединении client.set_compression(Some(threshold)); // Устанавливаем сжатие на соединении
} }
// Отправка пакета Login Success // Отправка пакета Login Success
client.write_packet(&Packet::build(0x02, |p| { client.write_packet(&Packet::build(LOGIN_SUCCESS_ID, |p| {
p.write_uuid(&uuid)?; p.write_uuid(&uuid)?;
p.write_string(&name)?; p.write_string(&name)?;
p.write_varint(0) p.write_varint(0)
})?)?; })?)?;
let packet = client.read_packet()?; client.read_packet(LOGIN_ACKNOWLEDGED_ID)?; // Пакет Login Acknowledged
if packet.id() != 0x03 {
return Err(ServerError::UnknownPacket(format!("Неизвестный пакет при ожидании Login Acknowledged")));
}
client.set_state(ConnectionState::Configuration)?; // Мы перешли в режим Configuration client.set_state(ConnectionState::Configuration)?; // Мы перешли в режим Configuration
// Получение бренда клиента из Serverbound Plugin Message // Получение бренда клиента из Serverbound Plugin Message
// Identifier канала откуда берется бренд: minecraft:brand // Identifier канала откуда берется бренд: minecraft:brand
let brand = loop { let brand = loop {
let mut packet = client.read_packet()?; let mut packet = client.read_packet(CONFIGURATION_SERVERBOUND_PLUGIN_MESSAGE_ID)?; // Пакет Serverbound Plugin Message
if packet.id() == 0x02 { // Пакет Serverbound Plugin Message
let identifier = packet.read_string()?; let identifier = packet.read_string()?;
let mut data = Vec::new(); let mut data = Vec::new();
@ -126,17 +137,9 @@ pub fn handle_connection(
} else { } else {
trigger_event!(client, plugin_message, &identifier, &data); trigger_event!(client, plugin_message, &identifier, &data);
} }
} else {
return Err(ServerError::UnknownPacket(format!("Неизвестный пакет при ожидании Serverbound Plugin Message")));
};
}; };
let mut packet = client.read_packet()?; let mut packet = client.read_packet(CONFIGURATION_CLIENT_INFORMATION_ID)?; // Пакет Client Information
// Пакет Client Information
if packet.id() != 0x00 {
return Err(ServerError::UnknownPacket(format!("Неизвестный пакет при ожидании Client Information")));
}
let locale = packet.read_string()?; // for example: en_us let locale = packet.read_string()?; // for example: en_us
let view_distance = packet.read_signed_byte()?; // client-side render distance in chunks let view_distance = packet.read_signed_byte()?; // client-side render distance in chunks
@ -163,22 +166,17 @@ pub fn handle_connection(
// TODO: Заюзать Listener'ы чтобы они подмешивали сюда чото // TODO: Заюзать Listener'ы чтобы они подмешивали сюда чото
client.write_packet(&Packet::empty(0x03))?; client.write_packet(&Packet::empty(CONFIGURATION_FINISH_ID))?;
client.read_packet(CONFIGURATION_ACKNOWLEDGE_FINISH_ID)?;
let packet = client.read_packet()?;
if packet.id() != 0x03 {
return Err(ServerError::UnknownPacket(format!("Неизвестный пакет при ожидании Acknowledge Finish Configuration")));
}
client.set_state(ConnectionState::Play)?; // Мы перешли в режим Play client.set_state(ConnectionState::Play)?; // Мы перешли в режим Play
// Дальше работаем с режимом игры // Дальше работаем с режимом игры
handle_play_state(client)?; handle_play_state(client)?;
}, },
_ => { _ => { // Тип подключения не рукопожатный
return Err(ServerError::UnknownPacket(format!("Неизвестный NextState при рукопожатии"))); return Err(ServerError::UnexpectedPacket);
} // Тип подключения не рукопожатный }
} }
Ok(()) Ok(())