diff --git a/src/server/mod.rs b/src/server/mod.rs index f46fd98..ffbc219 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -254,11 +254,25 @@ impl NetworkClient { } } NetworkClientState::Disconnected => { - self.connected = false; + if self.connected { + self.disconnect(None).await; + } } } } + async fn disconnect(&mut self, reason: Option<&str>) { + self.connected = false; + self.state = NetworkClientState::Disconnected; + // Send 0x40 Disconnect. + let mut disconnect = Disconnect::new(); + disconnect.reason.text = reason.unwrap_or("Disconnected").into(); + disconnect.write(&mut self.stream).await.unwrap(); + debug!("{:?}", disconnect); + // Give the client 10 seconds to disconnect before forcing it. + tokio::time::sleep(Duration::from_secs(10)).await; + } + /// Send a keep alive packet to the client. async fn keep_alive(&mut self) { // Keep alive ping to client. diff --git a/src/server/packets/clientbound.rs b/src/server/packets/clientbound.rs index 3eb409c..769561d 100644 --- a/src/server/packets/clientbound.rs +++ b/src/server/packets/clientbound.rs @@ -469,3 +469,44 @@ impl KeepAlivePing { Ok(()) } } + +#[derive(Debug, Clone)] +pub struct Disconnect { + pub reason: MCChat, +} +impl Into> for Disconnect { + fn into(self) -> Vec { + let mut out = vec![]; + let mut temp: Vec = MCVarInt::from(0x40).into(); // 0x40 Disconnect. + temp.extend_from_slice(&Into::>::into(self.reason)); + out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); + out.extend_from_slice(&temp); + out + } +} +impl TryFrom> for Disconnect { + type Error = &'static str; + fn try_from(_bytes: Vec) -> Result { + Err("unimplemented") + } +} +impl Disconnect { + pub fn new() -> Self { + Disconnect { + reason: MCChat { + text: "Disconnected".into(), + }, + } + } + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut keepalive = Disconnect::new(); + keepalive.reason = MCChat::read(t).await?; + Ok(keepalive) + } + pub async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { + for b in Into::>::into(self.clone()) { + write_byte(t, b).await?; + } + Ok(()) + } +}