Pumpkin/pumpkin/src/client/client_packet.rs
2024-07-30 21:49:34 +02:00

159 lines
5.0 KiB
Rust

use crate::{
protocol::{
client::{
config::CFinishConfig,
login::{CEncryptionRequest, CLoginSuccess},
status::{CPingResponse, CStatusResponse},
},
server::{
config::{SAcknowledgeFinishConfig, SClientInformation},
handshake::SHandShake,
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
status::{SPingRequest, SStatusRequest},
},
ConnectionState,
},
server::Server,
};
use super::{Client, PlayerConfig};
pub trait ClientPacketProcessor {
// Handshake
fn handle_handshake(&mut self, server: &mut Server, handshake: SHandShake);
// Status
fn handle_status_request(&mut self, server: &mut Server, status_request: SStatusRequest);
fn handle_ping_request(&mut self, server: &mut Server, ping_request: SPingRequest);
// Login
fn handle_login_start(&mut self, server: &mut Server, login_start: SLoginStart);
fn handle_encryption_response(
&mut self,
server: &mut Server,
encryption_response: SEncryptionResponse,
);
fn handle_plugin_response(
&mut self,
server: &mut Server,
plugin_response: SLoginPluginResponse,
);
fn handle_login_acknowledged(
&mut self,
server: &mut Server,
login_acknowledged: SLoginAcknowledged,
);
// Config
fn handle_client_information(
&mut self,
server: &mut Server,
client_information: SClientInformation,
);
fn handle_config_acknowledged(
&mut self,
server: &mut Server,
config_acknowledged: SAcknowledgeFinishConfig,
);
}
impl ClientPacketProcessor for Client {
fn handle_handshake(&mut self, _server: &mut Server, handshake: SHandShake) {
// TODO set protocol version and check protocol version
self.connection_state = handshake.next_state;
dbg!("handshake");
}
fn handle_status_request(&mut self, server: &mut Server, _status_request: SStatusRequest) {
dbg!("sending status");
let response = serde_json::to_string(&server.status_response).unwrap();
self.send_packet(CStatusResponse::new(response));
}
fn handle_ping_request(&mut self, _server: &mut Server, ping_request: SPingRequest) {
dbg!("ping");
self.send_packet(CPingResponse::new(ping_request.payload));
self.close();
}
fn handle_login_start(&mut self, server: &mut Server, login_start: SLoginStart) {
dbg!("login start");
self.name = Some(login_start.name);
self.uuid = Some(login_start.uuid);
let verify_token: [u8; 4] = rand::random();
let public_key_der = &server.public_key_der;
let packet = CEncryptionRequest::new(
"".into(),
public_key_der.len() as i32,
public_key_der,
verify_token.len() as i32,
&verify_token,
false, // TODO
);
self.send_packet(packet);
}
fn handle_encryption_response(
&mut self,
server: &mut Server,
encryption_response: SEncryptionResponse,
) {
dbg!("encryption response");
// should be impossible
if self.uuid.is_none() || self.name.is_none() {
self.kick("UUID or Name is none".into());
return;
}
self.enable_encryption(server, encryption_response.shared_secret)
.unwrap();
let packet = CLoginSuccess::new(self.uuid.unwrap(), self.name.clone().unwrap(), 0, false);
self.send_packet(packet);
}
fn handle_plugin_response(
&mut self,
_server: &mut Server,
_plugin_response: SLoginPluginResponse,
) {
}
fn handle_login_acknowledged(
&mut self,
_server: &mut Server,
login_acknowledged: SLoginAcknowledged,
) {
let _ = login_acknowledged;
self.connection_state = ConnectionState::Config;
dbg!("login achnowlaged");
}
fn handle_client_information(
&mut self,
_server: &mut Server,
client_information: SClientInformation,
) {
self.config = Some(PlayerConfig {
locale: client_information.locale,
view_distance: client_information.view_distance,
chat_mode: client_information.chat_mode,
chat_colors: client_information.chat_colors,
skin_parts: client_information.skin_parts,
main_hand: client_information.main_hand,
text_filtering: client_information.text_filtering,
server_listing: client_information.server_listing,
});
// We are done with configuring
self.send_packet(CFinishConfig::new());
}
fn handle_config_acknowledged(
&mut self,
server: &mut Server,
config_acknowledged: SAcknowledgeFinishConfig,
) {
dbg!("config acknowledged");
self.connection_state = ConnectionState::Play;
// generate a player
server.spawn_player(self);
}
}